[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree
zrouter-src-freebsd at zrouter.org
zrouter-src-freebsd at zrouter.org
Wed Feb 1 10:56:08 UTC 2012
details: http://zrouter.org/hg/FreeBSD/head//rev/f370dd4be562
changeset: 297:f370dd4be562
user: ray at terran.dlink.ua
date: Wed Feb 01 11:27:03 2012 +0200
description:
Add isci driver
diffstat:
head/sys/dev/isci/README | 14 +
head/sys/dev/isci/environment.h | 100 +
head/sys/dev/isci/isci.c | 650 +
head/sys/dev/isci/isci.h | 302 +
head/sys/dev/isci/isci_controller.c | 653 +
head/sys/dev/isci/isci_domain.c | 318 +
head/sys/dev/isci/isci_interrupt.c | 229 +
head/sys/dev/isci/isci_io_request.c | 923 +
head/sys/dev/isci/isci_logger.c | 351 +
head/sys/dev/isci/isci_oem_parameters.c | 176 +
head/sys/dev/isci/isci_remote_device.c | 298 +
head/sys/dev/isci/isci_sysctl.c | 229 +
head/sys/dev/isci/isci_task_request.c | 258 +
head/sys/dev/isci/isci_timer.c | 166 +
head/sys/dev/isci/sci_environment.h | 1 +
head/sys/dev/isci/scil/intel_ata.h | 654 +
head/sys/dev/isci/scil/intel_pci.h | 90 +
head/sys/dev/isci/scil/intel_sas.h | 977 +
head/sys/dev/isci/scil/intel_sat.h | 94 +
head/sys/dev/isci/scil/intel_sata.h | 284 +
head/sys/dev/isci/scil/intel_scsi.h | 540 +
head/sys/dev/isci/scil/sati.c | 1250 +
head/sys/dev/isci/scil/sati.h | 271 +
head/sys/dev/isci/scil/sati_abort_task_set.c | 177 +
head/sys/dev/isci/scil/sati_abort_task_set.h | 83 +
head/sys/dev/isci/scil/sati_atapi.c | 257 +
head/sys/dev/isci/scil/sati_atapi.h | 177 +
head/sys/dev/isci/scil/sati_callbacks.h | 481 +
head/sys/dev/isci/scil/sati_design.h | 169 +
head/sys/dev/isci/scil/sati_device.c | 245 +
head/sys/dev/isci/scil/sati_device.h | 203 +
head/sys/dev/isci/scil/sati_inquiry.c | 799 +
head/sys/dev/isci/scil/sati_inquiry.h | 114 +
head/sys/dev/isci/scil/sati_log_sense.c | 807 +
head/sys/dev/isci/scil/sati_log_sense.h | 87 +
head/sys/dev/isci/scil/sati_lun_reset.c | 122 +
head/sys/dev/isci/scil/sati_lun_reset.h | 79 +
head/sys/dev/isci/scil/sati_mode_pages.c | 372 +
head/sys/dev/isci/scil/sati_mode_pages.h | 144 +
head/sys/dev/isci/scil/sati_mode_select.c | 1115 +
head/sys/dev/isci/scil/sati_mode_select.h | 84 +
head/sys/dev/isci/scil/sati_mode_sense.c | 837 +
head/sys/dev/isci/scil/sati_mode_sense.h | 146 +
head/sys/dev/isci/scil/sati_mode_sense_10.c | 509 +
head/sys/dev/isci/scil/sati_mode_sense_10.h | 114 +
head/sys/dev/isci/scil/sati_mode_sense_6.c | 429 +
head/sys/dev/isci/scil/sati_mode_sense_6.h | 114 +
head/sys/dev/isci/scil/sati_move.c | 616 +
head/sys/dev/isci/scil/sati_move.h | 121 +
head/sys/dev/isci/scil/sati_passthrough.c | 465 +
head/sys/dev/isci/scil/sati_passthrough.h | 88 +
head/sys/dev/isci/scil/sati_read.c | 323 +
head/sys/dev/isci/scil/sati_read.h | 91 +
head/sys/dev/isci/scil/sati_read_buffer.c | 235 +
head/sys/dev/isci/scil/sati_read_buffer.h | 82 +
head/sys/dev/isci/scil/sati_read_capacity.c | 366 +
head/sys/dev/isci/scil/sati_read_capacity.h | 91 +
head/sys/dev/isci/scil/sati_reassign_blocks.c | 622 +
head/sys/dev/isci/scil/sati_reassign_blocks.h | 80 +
head/sys/dev/isci/scil/sati_report_luns.c | 124 +
head/sys/dev/isci/scil/sati_report_luns.h | 75 +
head/sys/dev/isci/scil/sati_request_sense.c | 353 +
head/sys/dev/isci/scil/sati_request_sense.h | 86 +
head/sys/dev/isci/scil/sati_start_stop_unit.c | 404 +
head/sys/dev/isci/scil/sati_start_stop_unit.h | 102 +
head/sys/dev/isci/scil/sati_synchronize_cache.c | 119 +
head/sys/dev/isci/scil/sati_synchronize_cache.h | 71 +
head/sys/dev/isci/scil/sati_test_unit_ready.c | 186 +
head/sys/dev/isci/scil/sati_test_unit_ready.h | 79 +
head/sys/dev/isci/scil/sati_translator_sequence.h | 361 +
head/sys/dev/isci/scil/sati_types.h | 152 +
head/sys/dev/isci/scil/sati_unmap.c | 609 +
head/sys/dev/isci/scil/sati_unmap.h | 135 +
head/sys/dev/isci/scil/sati_util.c | 2005 ++
head/sys/dev/isci/scil/sati_util.h | 393 +
head/sys/dev/isci/scil/sati_verify.c | 273 +
head/sys/dev/isci/scil/sati_verify.h | 83 +
head/sys/dev/isci/scil/sati_write.c | 321 +
head/sys/dev/isci/scil/sati_write.h | 91 +
head/sys/dev/isci/scil/sati_write_and_verify.c | 243 +
head/sys/dev/isci/scil/sati_write_and_verify.h | 90 +
head/sys/dev/isci/scil/sati_write_buffer.c | 254 +
head/sys/dev/isci/scil/sati_write_buffer.h | 78 +
head/sys/dev/isci/scil/sati_write_long.c | 259 +
head/sys/dev/isci/scil/sati_write_long.h | 83 +
head/sys/dev/isci/scil/sci_abstract_list.c | 599 +
head/sys/dev/isci/scil/sci_abstract_list.h | 871 +
head/sys/dev/isci/scil/sci_base_controller.c | 105 +
head/sys/dev/isci/scil/sci_base_controller.h | 347 +
head/sys/dev/isci/scil/sci_base_domain.c | 89 +
head/sys/dev/isci/scil/sci_base_domain.h | 309 +
head/sys/dev/isci/scil/sci_base_iterator.c | 182 +
head/sys/dev/isci/scil/sci_base_iterator.h | 134 +
head/sys/dev/isci/scil/sci_base_library.c | 103 +
head/sys/dev/isci/scil/sci_base_library.h | 197 +
head/sys/dev/isci/scil/sci_base_logger.c | 291 +
head/sys/dev/isci/scil/sci_base_logger.h | 131 +
head/sys/dev/isci/scil/sci_base_memory_descriptor_list.c | 168 +
head/sys/dev/isci/scil/sci_base_memory_descriptor_list.h | 168 +
head/sys/dev/isci/scil/sci_base_memory_descriptor_list_decorator.c | 149 +
head/sys/dev/isci/scil/sci_base_object.c | 118 +
head/sys/dev/isci/scil/sci_base_object.h | 142 +
head/sys/dev/isci/scil/sci_base_observer.c | 107 +
head/sys/dev/isci/scil/sci_base_observer.h | 167 +
head/sys/dev/isci/scil/sci_base_phy.c | 89 +
head/sys/dev/isci/scil/sci_base_phy.h | 213 +
head/sys/dev/isci/scil/sci_base_port.c | 88 +
head/sys/dev/isci/scil/sci_base_port.h | 233 +
head/sys/dev/isci/scil/sci_base_remote_device.c | 80 +
head/sys/dev/isci/scil/sci_base_remote_device.h | 298 +
head/sys/dev/isci/scil/sci_base_request.c | 79 +
head/sys/dev/isci/scil/sci_base_request.h | 209 +
head/sys/dev/isci/scil/sci_base_state.h | 110 +
head/sys/dev/isci/scil/sci_base_state_machine.c | 212 +
head/sys/dev/isci/scil/sci_base_state_machine.h | 157 +
head/sys/dev/isci/scil/sci_base_state_machine_logger.c | 217 +
head/sys/dev/isci/scil/sci_base_state_machine_logger.h | 137 +
head/sys/dev/isci/scil/sci_base_state_machine_observer.c | 99 +
head/sys/dev/isci/scil/sci_base_state_machine_observer.h | 138 +
head/sys/dev/isci/scil/sci_base_subject.c | 149 +
head/sys/dev/isci/scil/sci_base_subject.h | 157 +
head/sys/dev/isci/scil/sci_controller.h | 113 +
head/sys/dev/isci/scil/sci_controller_constants.h | 217 +
head/sys/dev/isci/scil/sci_fast_list.h | 339 +
head/sys/dev/isci/scil/sci_iterator.h | 129 +
head/sys/dev/isci/scil/sci_library.h | 111 +
head/sys/dev/isci/scil/sci_logger.h | 250 +
head/sys/dev/isci/scil/sci_memory_descriptor_list.h | 181 +
head/sys/dev/isci/scil/sci_memory_descriptor_list_decorator.h | 129 +
head/sys/dev/isci/scil/sci_object.h | 139 +
head/sys/dev/isci/scil/sci_overview.h | 251 +
head/sys/dev/isci/scil/sci_pool.h | 188 +
head/sys/dev/isci/scil/sci_simple_list.h | 350 +
head/sys/dev/isci/scil/sci_status.h | 418 +
head/sys/dev/isci/scil/sci_types.h | 280 +
head/sys/dev/isci/scil/sci_util.c | 72 +
head/sys/dev/isci/scil/sci_util.h | 164 +
head/sys/dev/isci/scil/scic_config_parameters.h | 346 +
head/sys/dev/isci/scil/scic_controller.h | 856 +
head/sys/dev/isci/scil/scic_io_request.h | 761 +
head/sys/dev/isci/scil/scic_library.h | 275 +
head/sys/dev/isci/scil/scic_logger.h | 136 +
head/sys/dev/isci/scil/scic_overview.h | 88 +
head/sys/dev/isci/scil/scic_phy.h | 462 +
head/sys/dev/isci/scil/scic_port.h | 239 +
head/sys/dev/isci/scil/scic_remote_device.h | 442 +
head/sys/dev/isci/scil/scic_sds_controller.c | 7042 ++++++++++
head/sys/dev/isci/scil/scic_sds_controller.h | 840 +
head/sys/dev/isci/scil/scic_sds_controller_registers.h | 598 +
head/sys/dev/isci/scil/scic_sds_library.c | 287 +
head/sys/dev/isci/scil/scic_sds_library.h | 118 +
head/sys/dev/isci/scil/scic_sds_logger.h | 93 +
head/sys/dev/isci/scil/scic_sds_pci.c | 247 +
head/sys/dev/isci/scil/scic_sds_pci.h | 138 +
head/sys/dev/isci/scil/scic_sds_phy.c | 4036 +++++
head/sys/dev/isci/scil/scic_sds_phy.h | 531 +
head/sys/dev/isci/scil/scic_sds_phy_registers.h | 270 +
head/sys/dev/isci/scil/scic_sds_port.c | 3662 +++++
head/sys/dev/isci/scil/scic_sds_port.h | 595 +
head/sys/dev/isci/scil/scic_sds_port_configuration_agent.c | 1133 +
head/sys/dev/isci/scil/scic_sds_port_configuration_agent.h | 128 +
head/sys/dev/isci/scil/scic_sds_port_registers.h | 139 +
head/sys/dev/isci/scil/scic_sds_remote_device.c | 2727 +++
head/sys/dev/isci/scil/scic_sds_remote_device.h | 646 +
head/sys/dev/isci/scil/scic_sds_remote_node_context.c | 1500 ++
head/sys/dev/isci/scil/scic_sds_remote_node_context.h | 382 +
head/sys/dev/isci/scil/scic_sds_remote_node_table.c | 660 +
head/sys/dev/isci/scil/scic_sds_remote_node_table.h | 190 +
head/sys/dev/isci/scil/scic_sds_request.c | 2890 ++++
head/sys/dev/isci/scil/scic_sds_request.h | 543 +
head/sys/dev/isci/scil/scic_sds_sgpio.c | 298 +
head/sys/dev/isci/scil/scic_sds_smp_remote_device.c | 371 +
head/sys/dev/isci/scil/scic_sds_smp_request.c | 872 +
head/sys/dev/isci/scil/scic_sds_smp_request.h | 83 +
head/sys/dev/isci/scil/scic_sds_ssp_request.c | 340 +
head/sys/dev/isci/scil/scic_sds_stp_packet_request.c | 978 +
head/sys/dev/isci/scil/scic_sds_stp_packet_request.h | 171 +
head/sys/dev/isci/scil/scic_sds_stp_pio_request.h | 131 +
head/sys/dev/isci/scil/scic_sds_stp_remote_device.c | 1098 +
head/sys/dev/isci/scil/scic_sds_stp_request.c | 2583 +++
head/sys/dev/isci/scil/scic_sds_stp_request.h | 280 +
head/sys/dev/isci/scil/scic_sds_unsolicited_frame_control.c | 402 +
head/sys/dev/isci/scil/scic_sds_unsolicited_frame_control.h | 305 +
head/sys/dev/isci/scil/scic_sgpio.h | 299 +
head/sys/dev/isci/scil/scic_task_request.h | 181 +
head/sys/dev/isci/scil/scic_user_callback.h | 1146 +
head/sys/dev/isci/scil/scif_config_parameters.h | 181 +
head/sys/dev/isci/scil/scif_controller.h | 454 +
head/sys/dev/isci/scil/scif_domain.h | 185 +
head/sys/dev/isci/scil/scif_io_request.h | 243 +
head/sys/dev/isci/scil/scif_library.h | 196 +
head/sys/dev/isci/scil/scif_logger.h | 118 +
head/sys/dev/isci/scil/scif_overview.h | 116 +
head/sys/dev/isci/scil/scif_remote_device.h | 295 +
head/sys/dev/isci/scil/scif_sas_constants.h | 79 +
head/sys/dev/isci/scil/scif_sas_controller.c | 1249 +
head/sys/dev/isci/scil/scif_sas_controller.h | 308 +
head/sys/dev/isci/scil/scif_sas_controller_state_handlers.c | 1845 ++
head/sys/dev/isci/scil/scif_sas_controller_states.c | 460 +
head/sys/dev/isci/scil/scif_sas_design.h | 348 +
head/sys/dev/isci/scil/scif_sas_domain.c | 1536 ++
head/sys/dev/isci/scil/scif_sas_domain.h | 328 +
head/sys/dev/isci/scil/scif_sas_domain_state_handlers.c | 1630 ++
head/sys/dev/isci/scil/scif_sas_domain_states.c | 612 +
head/sys/dev/isci/scil/scif_sas_high_priority_request_queue.c | 161 +
head/sys/dev/isci/scil/scif_sas_high_priority_request_queue.h | 123 +
head/sys/dev/isci/scil/scif_sas_internal_io_request.c | 282 +
head/sys/dev/isci/scil/scif_sas_internal_io_request.h | 157 +
head/sys/dev/isci/scil/scif_sas_io_request.c | 820 +
head/sys/dev/isci/scil/scif_sas_io_request.h | 152 +
head/sys/dev/isci/scil/scif_sas_io_request_state_handlers.c | 417 +
head/sys/dev/isci/scil/scif_sas_io_request_states.c | 286 +
head/sys/dev/isci/scil/scif_sas_library.c | 270 +
head/sys/dev/isci/scil/scif_sas_library.h | 105 +
head/sys/dev/isci/scil/scif_sas_logger.h | 94 +
head/sys/dev/isci/scil/scif_sas_remote_device.c | 794 +
head/sys/dev/isci/scil/scif_sas_remote_device.h | 502 +
head/sys/dev/isci/scil/scif_sas_remote_device_ready_substate_handlers.c | 779 +
head/sys/dev/isci/scil/scif_sas_remote_device_ready_substates.c | 290 +
head/sys/dev/isci/scil/scif_sas_remote_device_starting_substate_handlers.c | 317 +
head/sys/dev/isci/scil/scif_sas_remote_device_starting_substates.c | 143 +
head/sys/dev/isci/scil/scif_sas_remote_device_state_handlers.c | 1161 +
head/sys/dev/isci/scil/scif_sas_remote_device_states.c | 549 +
head/sys/dev/isci/scil/scif_sas_request.c | 183 +
head/sys/dev/isci/scil/scif_sas_request.h | 221 +
head/sys/dev/isci/scil/scif_sas_sati_binding.h | 253 +
head/sys/dev/isci/scil/scif_sas_smp_activity_clear_affiliation.c | 252 +
head/sys/dev/isci/scil/scif_sas_smp_io_request.c | 600 +
head/sys/dev/isci/scil/scif_sas_smp_io_request.h | 138 +
head/sys/dev/isci/scil/scif_sas_smp_phy.c | 335 +
head/sys/dev/isci/scil/scif_sas_smp_phy.h | 186 +
head/sys/dev/isci/scil/scif_sas_smp_remote_device.c | 2632 +++
head/sys/dev/isci/scil/scif_sas_smp_remote_device.h | 431 +
head/sys/dev/isci/scil/scif_sas_stp_io_request.c | 623 +
head/sys/dev/isci/scil/scif_sas_stp_io_request.h | 101 +
head/sys/dev/isci/scil/scif_sas_stp_remote_device.c | 215 +
head/sys/dev/isci/scil/scif_sas_stp_remote_device.h | 119 +
head/sys/dev/isci/scil/scif_sas_stp_task_request.c | 265 +
head/sys/dev/isci/scil/scif_sas_stp_task_request.h | 106 +
head/sys/dev/isci/scil/scif_sas_task_request.c | 481 +
head/sys/dev/isci/scil/scif_sas_task_request.h | 143 +
head/sys/dev/isci/scil/scif_sas_task_request_state_handlers.c | 404 +
head/sys/dev/isci/scil/scif_sas_task_request_states.c | 287 +
head/sys/dev/isci/scil/scif_sas_timer.c | 123 +
head/sys/dev/isci/scil/scif_task_request.h | 129 +
head/sys/dev/isci/scil/scif_user_callback.h | 1049 +
head/sys/dev/isci/scil/scu_bios_definitions.h | 1002 +
head/sys/dev/isci/scil/scu_completion_codes.h | 263 +
head/sys/dev/isci/scil/scu_constants.h | 154 +
head/sys/dev/isci/scil/scu_event_codes.h | 343 +
head/sys/dev/isci/scil/scu_registers.h | 2121 +++
head/sys/dev/isci/scil/scu_remote_node_context.h | 242 +
head/sys/dev/isci/scil/scu_task_context.h | 965 +
head/sys/dev/isci/scil/scu_unsolicited_frame.h | 122 +
head/sys/dev/isci/scil/scu_viit_data.h | 186 +
head/sys/dev/isci/types.h | 53 +
256 files changed, 111924 insertions(+), 0 deletions(-)
diffs (112948 lines):
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/README Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,14 @@
+FreeBSD Driver for Intel(R) C600 SAS Controller
+===============================================
+
+This driver has been developed for use with FreeBSD, version 9.0 and later.
+
+This driver uses an OS-agnostic abstraction layer library named SCIL that is
+published by Intel specifically for the C600 SAS controller. The SAS
+controller has no firmware, so the driver is extensive and using SCIL
+minimizes the development and maintenance cost of the driver.
+
+The FreeBSD implementation files are in the isci directory, and SCIL files
+are in the isci/scil subdirectory. As Intel publishes new versions of SCIL
+(to add features or fix bugs), the isci/scil subdirectory will be updated
+appropriately.
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/environment.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/environment.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,100 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef ENVIRONMENT_H_
+#define ENVIRONMENT_H_
+
+/**
+ * @file
+ *
+ * @brief Types and macros specific to the FreeBSD environment.
+ */
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/libkern.h>
+#include <machine/bus.h>
+#include <opt_isci.h>
+
+typedef int8_t S8;
+typedef uint8_t U8;
+
+typedef int16_t S16;
+typedef uint16_t U16;
+
+typedef int32_t S32;
+typedef uint32_t U32;
+
+typedef int64_t S64;
+typedef uint64_t U64;
+
+/* Technically, this should be defined as bus_addr_t, but SCIL makes some
+ * incorrect assumptions in some of its physical address calculations which
+ * necessitate using uint64_t here to avoid compiler warnings. This is
+ * easier for now than modifying SCIL, and works just as well.
+ */
+typedef uint64_t SCI_PHYSICAL_ADDRESS;
+
+typedef U64 SATI_LBA;
+typedef void * FUNCPTR;
+
+#define sci_cb_physical_address_upper(address) ((uint32_t)((address)>>32))
+#define sci_cb_physical_address_lower(address) ((uint32_t)((address)&0xFFFFFFFF))
+#define sci_cb_make_physical_address(physical_address, address_upper, address_lower) \
+ ((physical_address) = ((U64)(address_upper))<<32 | (address_lower))
+
+#define INLINE __inline
+
+#define PLACEMENT_HINTS(...)
+
+#define SCIC_SDS_4_ENABLED 1
+#define PBG_BUILD 1
+#define PHY_MAX_LINK_SPEED_GENERATION 3
+
+/* SCIL defines logging as SCI_LOGGING, but the FreeBSD driver name is ISCI.
+ So we define ISCI_LOGGING as the option exported to the kernel, and
+ translate it here. */
+#ifdef ISCI_LOGGING
+#define SCI_LOGGING
+#endif
+
+#define __SCI_LIBRARY_MAJOR_VERSION__ 3
+#define __SCI_LIBRARY_MINOR_VERSION__ 1
+#define __SCI_LIBRARY_BUILD_VERSION__ 7142
+
+#define SATI_TRANSPORT_SUPPORTS_SATA
+#define SATI_TRANSPORT_SUPPORTS_SAS
+#define USE_ABSTRACT_LIST_FUNCTIONS
+
+#define ASSERT(cond)
+#define assert(cond)
+
+#endif /* ENVIRONMENT_H_ */
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,650 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <sys/sysctl.h>
+#include <sys/malloc.h>
+
+#include <cam/cam_periph.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/isci/scil/scic_logger.h>
+#include <dev/isci/scil/scic_library.h>
+#include <dev/isci/scil/scic_user_callback.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_library.h>
+#include <dev/isci/scil/scif_logger.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+MALLOC_DEFINE(M_ISCI, "isci", "isci driver memory allocations");
+
+struct isci_softc *g_isci;
+uint32_t g_isci_debug_level = 0;
+
+static int isci_probe(device_t);
+static int isci_attach(device_t);
+static int isci_detach(device_t);
+
+int isci_initialize(struct isci_softc *isci);
+
+void isci_allocate_dma_buffer_callback(void *arg, bus_dma_segment_t *seg,
+ int nseg, int error);
+
+static devclass_t isci_devclass;
+
+static device_method_t isci_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, isci_probe),
+ DEVMETHOD(device_attach, isci_attach),
+ DEVMETHOD(device_detach, isci_detach),
+ { 0, 0 }
+};
+
+static driver_t isci_pci_driver = {
+ "isci",
+ isci_pci_methods,
+ sizeof(struct isci_softc),
+};
+
+DRIVER_MODULE(isci, pci, isci_pci_driver, isci_devclass, 0, 0);
+
+static struct _pcsid
+{
+ u_int32_t type;
+ const char *desc;
+} pci_ids[] = {
+ { 0x1d608086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d618086, "Intel(R) C600 Series Chipset SAS Controller (SATA mode)" },
+ { 0x1d628086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d638086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d648086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d658086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d668086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d678086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d688086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d698086, "Intel(R) C600 Series Chipset SAS Controller" },
+ { 0x1d6a8086, "Intel(R) C600 Series Chipset SAS Controller (SATA mode)" },
+ { 0x1d6b8086, "Intel(R) C600 Series Chipset SAS Controller (SATA mode)" },
+ { 0x00000000, NULL }
+};
+
+static int
+isci_probe (device_t device)
+{
+ u_int32_t type = pci_get_devid(device);
+ struct _pcsid *ep = pci_ids;
+
+ while (ep->type && ep->type != type)
+ ++ep;
+
+ if (ep->desc)
+ {
+ device_set_desc(device, ep->desc);
+ return (0);
+ }
+ else
+ return (ENXIO);
+}
+
+static int
+isci_allocate_pci_memory(struct isci_softc *isci)
+{
+ int i;
+
+ for (i = 0; i < ISCI_NUM_PCI_BARS; i++)
+ {
+ struct ISCI_PCI_BAR *pci_bar = &isci->pci_bar[i];
+
+ pci_bar->resource_id = PCIR_BAR(i*2);
+ pci_bar->resource = bus_alloc_resource(isci->device,
+ SYS_RES_MEMORY, &pci_bar->resource_id, 0, ~0, 1,
+ RF_ACTIVE);
+
+ if(pci_bar->resource == NULL)
+ isci_log_message(0, "ISCI",
+ "unable to allocate pci resource\n");
+ else {
+ pci_bar->bus_tag = rman_get_bustag(pci_bar->resource);
+ pci_bar->bus_handle =
+ rman_get_bushandle(pci_bar->resource);
+ }
+ }
+
+ return (0);
+}
+
+static int
+isci_attach(device_t device)
+{
+ int error;
+ struct isci_softc *isci = DEVICE2SOFTC(device);
+
+ g_isci = isci;
+ isci->device = device;
+
+ isci_allocate_pci_memory(isci);
+
+ error = isci_initialize(isci);
+
+ if (error)
+ {
+ isci_detach(device);
+ return (error);
+ }
+
+ isci_interrupt_setup(isci);
+ isci_sysctl_initialize(isci);
+
+ return (0);
+}
+
+static int
+isci_detach(device_t device)
+{
+ struct isci_softc *isci = DEVICE2SOFTC(device);
+ int i;
+
+ for (i = 0; i < isci->controller_count; i++) {
+ struct ISCI_CONTROLLER *controller = &isci->controllers[i];
+ SCI_STATUS status;
+
+ if (controller->scif_controller_handle != NULL) {
+ scic_controller_disable_interrupts(
+ scif_controller_get_scic_handle(controller->scif_controller_handle));
+
+ mtx_lock(&controller->lock);
+ status = scif_controller_stop(controller->scif_controller_handle, 0);
+ mtx_unlock(&controller->lock);
+
+ while (controller->is_started == TRUE) {
+ /* Now poll for interrupts until the controller stop complete
+ * callback is received.
+ */
+ mtx_lock(&controller->lock);
+ isci_interrupt_poll_handler(controller);
+ mtx_unlock(&controller->lock);
+ pause("isci", 1);
+ }
+
+ if(controller->sim != NULL) {
+ mtx_lock(&controller->lock);
+ xpt_free_path(controller->path);
+ xpt_bus_deregister(cam_sim_path(controller->sim));
+ cam_sim_free(controller->sim, TRUE);
+ mtx_unlock(&controller->lock);
+ }
+ }
+
+ if (controller->timer_memory != NULL)
+ free(controller->timer_memory, M_ISCI);
+
+ if (controller->remote_device_memory != NULL)
+ free(controller->remote_device_memory, M_ISCI);
+ }
+
+ /* The SCIF controllers have been stopped, so we can now
+ * free the SCI library memory.
+ */
+ if (isci->sci_library_memory != NULL)
+ free(isci->sci_library_memory, M_ISCI);
+
+ for (i = 0; i < ISCI_NUM_PCI_BARS; i++)
+ {
+ struct ISCI_PCI_BAR *pci_bar = &isci->pci_bar[i];
+
+ if (pci_bar->resource != NULL)
+ bus_release_resource(device, SYS_RES_MEMORY,
+ pci_bar->resource_id, pci_bar->resource);
+ }
+
+ for (i = 0; i < isci->num_interrupts; i++)
+ {
+ struct ISCI_INTERRUPT_INFO *interrupt_info;
+
+ interrupt_info = &isci->interrupt_info[i];
+
+ if(interrupt_info->tag != NULL)
+ bus_teardown_intr(device, interrupt_info->res,
+ interrupt_info->tag);
+
+ if(interrupt_info->res != NULL)
+ bus_release_resource(device, SYS_RES_IRQ,
+ rman_get_rid(interrupt_info->res),
+ interrupt_info->res);
+
+ pci_release_msi(device);
+ }
+
+ return (0);
+}
+
+int
+isci_initialize(struct isci_softc *isci)
+{
+ int error;
+ uint32_t status = 0;
+ uint32_t library_object_size;
+ uint32_t verbosity_mask;
+ uint32_t scic_log_object_mask;
+ uint32_t scif_log_object_mask;
+ uint8_t *header_buffer;
+
+ library_object_size = scif_library_get_object_size(SCI_MAX_CONTROLLERS);
+
+ isci->sci_library_memory =
+ malloc(library_object_size, M_ISCI, M_NOWAIT | M_ZERO );
+
+ isci->sci_library_handle = scif_library_construct(
+ isci->sci_library_memory, SCI_MAX_CONTROLLERS);
+
+ sci_object_set_association( isci->sci_library_handle, (void *)isci);
+
+ verbosity_mask = (1<<SCI_LOG_VERBOSITY_ERROR) |
+ (1<<SCI_LOG_VERBOSITY_WARNING) | (1<<SCI_LOG_VERBOSITY_INFO) |
+ (1<<SCI_LOG_VERBOSITY_TRACE);
+
+ scic_log_object_mask = 0xFFFFFFFF;
+ scic_log_object_mask &= ~SCIC_LOG_OBJECT_COMPLETION_QUEUE;
+ scic_log_object_mask &= ~SCIC_LOG_OBJECT_SSP_IO_REQUEST;
+ scic_log_object_mask &= ~SCIC_LOG_OBJECT_STP_IO_REQUEST;
+ scic_log_object_mask &= ~SCIC_LOG_OBJECT_SMP_IO_REQUEST;
+ scic_log_object_mask &= ~SCIC_LOG_OBJECT_CONTROLLER;
+
+ scif_log_object_mask = 0xFFFFFFFF;
+ scif_log_object_mask &= ~SCIF_LOG_OBJECT_CONTROLLER;
+ scif_log_object_mask &= ~SCIF_LOG_OBJECT_IO_REQUEST;
+
+ TUNABLE_INT_FETCH("hw.isci.debug_level", &g_isci_debug_level);
+
+ sci_logger_enable(sci_object_get_logger(isci->sci_library_handle),
+ scif_log_object_mask, verbosity_mask);
+
+ sci_logger_enable(sci_object_get_logger(
+ scif_library_get_scic_handle(isci->sci_library_handle)),
+ scic_log_object_mask, verbosity_mask);
+
+ header_buffer = (uint8_t *)&isci->pci_common_header;
+ for (uint8_t i = 0; i < sizeof(isci->pci_common_header); i++)
+ header_buffer[i] = pci_read_config(isci->device, i, 1);
+
+ scic_library_set_pci_info(
+ scif_library_get_scic_handle(isci->sci_library_handle),
+ &isci->pci_common_header);
+
+ isci->oem_parameters_found = FALSE;
+
+ isci_get_oem_parameters(isci);
+
+ /* trigger interrupt if 32 completions occur before timeout expires */
+ isci->coalesce_number = 32;
+
+ /* trigger interrupt if 2 microseconds elapse after a completion occurs,
+ * regardless if "coalesce_number" completions have occurred
+ */
+ isci->coalesce_timeout = 2;
+
+ isci->controller_count = scic_library_get_pci_device_controller_count(
+ scif_library_get_scic_handle(isci->sci_library_handle));
+
+ for (int index = 0; index < isci->controller_count; index++) {
+ struct ISCI_CONTROLLER *controller = &isci->controllers[index];
+ SCI_CONTROLLER_HANDLE_T scif_controller_handle;
+
+ controller->index = index;
+ isci_controller_construct(controller, isci);
+
+ scif_controller_handle = controller->scif_controller_handle;
+
+ status = isci_controller_initialize(controller);
+
+ if(status != SCI_SUCCESS) {
+ isci_log_message(0, "ISCI",
+ "isci_controller_initialize FAILED: %x\n",
+ status);
+ return (status);
+ }
+
+ error = isci_controller_allocate_memory(controller);
+
+ if (error != 0)
+ return (error);
+
+ scif_controller_set_interrupt_coalescence(
+ scif_controller_handle, isci->coalesce_number,
+ isci->coalesce_timeout);
+ }
+
+ /* FreeBSD provides us a hook to ensure we get a chance to start
+ * our controllers and complete initial domain discovery before
+ * it searches for the boot device. Once we're done, we'll
+ * disestablish the hook, signaling the kernel that is can proceed
+ * with the boot process.
+ */
+ isci->config_hook.ich_func = &isci_controller_start;
+ isci->config_hook.ich_arg = &isci->controllers[0];
+
+ if (config_intrhook_establish(&isci->config_hook) != 0)
+ isci_log_message(0, "ISCI",
+ "config_intrhook_establish failed!\n");
+
+ return (status);
+}
+
+void
+isci_allocate_dma_buffer_callback(void *arg, bus_dma_segment_t *seg,
+ int nseg, int error)
+{
+ struct ISCI_MEMORY *memory = (struct ISCI_MEMORY *)arg;
+
+ memory->error = error;
+
+ if (nseg != 1 || error != 0)
+ isci_log_message(0, "ISCI",
+ "Failed to allocate physically contiguous memory!\n");
+ else
+ memory->physical_address = seg->ds_addr;
+}
+
+int
+isci_allocate_dma_buffer(device_t device, struct ISCI_MEMORY *memory)
+{
+ uint32_t status;
+
+ status = bus_dma_tag_create(bus_get_dma_tag(device),
+ 0x40 /* cacheline alignment */, 0x0, BUS_SPACE_MAXADDR,
+ BUS_SPACE_MAXADDR, NULL, NULL, memory->size,
+ 0x1 /* we want physically contiguous */,
+ memory->size, 0, NULL, NULL, &memory->dma_tag);
+
+ if(status == ENOMEM) {
+ isci_log_message(0, "ISCI", "bus_dma_tag_create failed\n");
+ return (status);
+ }
+
+ status = bus_dmamem_alloc(memory->dma_tag,
+ (void **)&memory->virtual_address, BUS_DMA_ZERO, &memory->dma_map);
+
+ if(status == ENOMEM)
+ {
+ isci_log_message(0, "ISCI", "bus_dmamem_alloc failed\n");
+ return (status);
+ }
+
+ status = bus_dmamap_load(memory->dma_tag, memory->dma_map,
+ (void *)memory->virtual_address, memory->size,
+ isci_allocate_dma_buffer_callback, memory, 0);
+
+ if(status == EINVAL)
+ {
+ isci_log_message(0, "ISCI", "bus_dmamap_load failed\n");
+ return (status);
+ }
+
+ return (0);
+}
+
+/**
+ * @brief This callback method asks the user to associate the supplied
+ * lock with an operating environment specific locking construct.
+ *
+ * @param[in] controller This parameter specifies the controller with
+ * which this lock is to be associated.
+ * @param[in] lock This parameter specifies the lock for which the
+ * user should associate an operating environment specific
+ * locking object.
+ *
+ * @see The SCI_LOCK_LEVEL enumeration for more information.
+ *
+ * @return none.
+ */
+void
+scif_cb_lock_associate(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_LOCK_HANDLE_T lock)
+{
+
+}
+
+/**
+ * @brief This callback method asks the user to de-associate the supplied
+ * lock with an operating environment specific locking construct.
+ *
+ * @param[in] controller This parameter specifies the controller with
+ * which this lock is to be de-associated.
+ * @param[in] lock This parameter specifies the lock for which the
+ * user should de-associate an operating environment specific
+ * locking object.
+ *
+ * @see The SCI_LOCK_LEVEL enumeration for more information.
+ *
+ * @return none.
+ */
+void
+scif_cb_lock_disassociate(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_LOCK_HANDLE_T lock)
+{
+
+}
+
+
+/**
+ * @brief This callback method asks the user to acquire/get the lock.
+ * This method should pend until the lock has been acquired.
+ *
+ * @param[in] controller This parameter specifies the controller with
+ * which this lock is associated.
+ * @param[in] lock This parameter specifies the lock to be acquired.
+ *
+ * @return none
+ */
+void
+scif_cb_lock_acquire(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_LOCK_HANDLE_T lock)
+{
+
+}
+
+/**
+ * @brief This callback method asks the user to release a lock.
+ *
+ * @param[in] controller This parameter specifies the controller with
+ * which this lock is associated.
+ * @param[in] lock This parameter specifies the lock to be released.
+ *
+ * @return none
+ */
+void
+scif_cb_lock_release(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_LOCK_HANDLE_T lock)
+{
+}
+
+/**
+ * @brief This callback method creates an OS specific deferred task
+ * for internal usage. The handler to deferred task is stored by OS
+ * driver.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_start_internal_io_task_create(SCI_CONTROLLER_HANDLE_T controller)
+{
+
+}
+
+/**
+ * @brief This callback method schedules a OS specific deferred task.
+ *
+ * @param[in] controller This parameter specifies the controller
+ * object with which this callback is associated.
+ * @param[in] start_internal_io_task_routine This parameter specifies the
+ * sci start_internal_io routine.
+ * @param[in] context This parameter specifies a handle to a parameter
+ * that will be passed into the "start_internal_io_task_routine"
+ * when it is invoked.
+ *
+ * @return none
+ */
+void
+scif_cb_start_internal_io_task_schedule(SCI_CONTROLLER_HANDLE_T scif_controller,
+ FUNCPTR start_internal_io_task_routine, void *context)
+{
+ /** @todo Use FreeBSD tasklet to defer this routine to a later time,
+ * rather than calling the routine inline.
+ */
+ SCI_START_INTERNAL_IO_ROUTINE sci_start_internal_io_routine =
+ (SCI_START_INTERNAL_IO_ROUTINE)start_internal_io_task_routine;
+
+ sci_start_internal_io_routine(context);
+}
+
+/**
+ * @brief In this method the user must write to PCI memory via access.
+ * This method is used for access to memory space and IO space.
+ *
+ * @param[in] controller The controller for which to read a DWORD.
+ * @param[in] address This parameter depicts the address into
+ * which to write.
+ * @param[out] write_value This parameter depicts the value being written
+ * into the PCI memory location.
+ *
+ * @todo These PCI memory access calls likely needs to be optimized into macros?
+ */
+void
+scic_cb_pci_write_dword(SCI_CONTROLLER_HANDLE_T scic_controller,
+ void *address, uint32_t write_value)
+{
+ SCI_CONTROLLER_HANDLE_T scif_controller =
+ (SCI_CONTROLLER_HANDLE_T) sci_object_get_association(scic_controller);
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *) sci_object_get_association(scif_controller);
+ struct isci_softc *isci = isci_controller->isci;
+ uint32_t bar = (uint32_t)(((POINTER_UINT)address & 0xF0000000) >> 28);
+ bus_size_t offset = (bus_size_t)((POINTER_UINT)address & 0x0FFFFFFF);
+
+ bus_space_write_4(isci->pci_bar[bar].bus_tag,
+ isci->pci_bar[bar].bus_handle, offset, write_value);
+}
+
+/**
+ * @brief In this method the user must read from PCI memory via access.
+ * This method is used for access to memory space and IO space.
+ *
+ * @param[in] controller The controller for which to read a DWORD.
+ * @param[in] address This parameter depicts the address from
+ * which to read.
+ *
+ * @return The value being returned from the PCI memory location.
+ *
+ * @todo This PCI memory access calls likely need to be optimized into macro?
+ */
+uint32_t
+scic_cb_pci_read_dword(SCI_CONTROLLER_HANDLE_T scic_controller, void *address)
+{
+ SCI_CONTROLLER_HANDLE_T scif_controller =
+ (SCI_CONTROLLER_HANDLE_T)sci_object_get_association(scic_controller);
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
+ struct isci_softc *isci = isci_controller->isci;
+ uint32_t bar = (uint32_t)(((POINTER_UINT)address & 0xF0000000) >> 28);
+ bus_size_t offset = (bus_size_t)((POINTER_UINT)address & 0x0FFFFFFF);
+
+ return (bus_space_read_4(isci->pci_bar[bar].bus_tag,
+ isci->pci_bar[bar].bus_handle, offset));
+}
+
+/**
+ * @brief This method is called when the core requires the OS driver
+ * to stall execution. This method is utilized during initialization
+ * or non-performance paths only.
+ *
+ * @param[in] microseconds This parameter specifies the number of
+ * microseconds for which to stall. The operating system driver
+ * is allowed to round this value up where necessary.
+ *
+ * @return none.
+ */
+void
+scic_cb_stall_execution(uint32_t microseconds)
+{
+
+ DELAY(microseconds);
+}
+
+/**
+ * @brief In this method the user must return the base address register (BAR)
+ * value for the supplied base address register number.
+ *
+ * @param[in] controller The controller for which to retrieve the bar number.
+ * @param[in] bar_number This parameter depicts the BAR index/number to be read.
+ *
+ * @return Return a pointer value indicating the contents of the BAR.
+ * @retval NULL indicates an invalid BAR index/number was specified.
+ * @retval All other values indicate a valid VIRTUAL address from the BAR.
+ */
+void *
+scic_cb_pci_get_bar(SCI_CONTROLLER_HANDLE_T controller,
+ uint16_t bar_number)
+{
+
+ return ((void *)(POINTER_UINT)((uint32_t)bar_number << 28));
+}
+
+/**
+ * @brief This method informs the SCI Core user that a phy/link became
+ * ready, but the phy is not allowed in the port. In some
+ * situations the underlying hardware only allows for certain phy
+ * to port mappings. If these mappings are violated, then this
+ * API is invoked.
+ *
+ * @param[in] controller This parameter represents the controller which
+ * contains the port.
+ * @param[in] port This parameter specifies the SCI port object for which
+ * the callback is being invoked.
+ * @param[in] phy This parameter specifies the phy that came ready, but the
+ * phy can't be a valid member of the port.
+ *
+ * @return none
+ */
+void
+scic_cb_port_invalid_link_up(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_PORT_HANDLE_T port, SCI_PHY_HANDLE_T phy)
+{
+
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,302 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/types.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+
+#include <dev/isci/environment.h>
+#include <dev/isci/scil/intel_pci.h>
+
+#include <dev/isci/scil/sci_types.h>
+#include <dev/isci/scil/sci_object.h>
+#include <dev/isci/scil/sci_status.h>
+#include <dev/isci/scil/sci_pool.h>
+#include <dev/isci/scil/sci_fast_list.h>
+
+#include <dev/isci/scil/sci_controller_constants.h>
+
+#include <dev/isci/scil/scic_controller.h>
+#include <dev/isci/scil/scic_config_parameters.h>
+
+#define DEVICE2SOFTC(dev) ((struct isci_softc *) device_get_softc(dev))
+
+#define DEVICE_TIMEOUT 1000
+#define SCI_MAX_TIMERS 32
+
+#define ISCI_NUM_PCI_BARS 2
+#define ISCI_MAX_LUN 8
+
+MALLOC_DECLARE(M_ISCI);
+
+struct ISCI_TIMER {
+ struct callout callout;
+ SCI_TIMER_CALLBACK_T callback;
+ void *cookie;
+ BOOL is_started;
+};
+
+struct ISCI_REMOTE_DEVICE {
+ uint32_t index;
+ struct ISCI_DOMAIN *domain;
+ SCI_REMOTE_DEVICE_HANDLE_T sci_object;
+ BOOL is_resetting;
+ uint32_t frozen_lun_mask;
+ SCI_FAST_LIST_ELEMENT_T pending_device_reset_element;
+};
+
+struct ISCI_DOMAIN {
+ struct ISCI_CONTROLLER *controller;
+ SCI_DOMAIN_HANDLE_T sci_object;
+ uint8_t index;
+
+};
+
+struct ISCI_MEMORY
+{
+ bus_addr_t physical_address;
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ POINTER_UINT virtual_address;
+ uint32_t size;
+ int error;
+};
+
+struct ISCI_INTERRUPT_INFO
+{
+ SCIC_CONTROLLER_HANDLER_METHODS_T *handlers;
+ void *interrupt_target_handle;
+ struct resource *res;
+ int rid;
+ void *tag;
+
+};
+
+struct ISCI_CONTROLLER
+{
+ struct isci_softc *isci;
+ uint8_t index;
+ SCI_CONTROLLER_HANDLE_T scif_controller_handle;
+ struct ISCI_DOMAIN domain[SCI_MAX_DOMAINS];
+ BOOL is_started;
+ uint32_t initial_discovery_mask;
+ BOOL is_frozen;
+ uint8_t *remote_device_memory;
+ struct ISCI_MEMORY cached_controller_memory;
+ struct ISCI_MEMORY uncached_controller_memory;
+ struct ISCI_MEMORY request_memory;
+ bus_dma_tag_t buffer_dma_tag;
+ struct mtx lock;
+ struct cam_sim *sim;
+ struct cam_path *path;
+ struct ISCI_REMOTE_DEVICE *remote_device[SCI_MAX_REMOTE_DEVICES];
+ void *timer_memory;
+ SCIC_OEM_PARAMETERS_T oem_parameters;
+ uint32_t oem_parameters_version;
+ uint32_t queue_depth;
+ uint32_t sim_queue_depth;
+ SCI_FAST_LIST_T pending_device_reset_list;
+
+ SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl;
+
+ SCI_POOL_CREATE(remote_device_pool, struct ISCI_REMOTE_DEVICE *, SCI_MAX_REMOTE_DEVICES);
+ SCI_POOL_CREATE(request_pool, struct ISCI_REQUEST *, SCI_MAX_IO_REQUESTS);
+ SCI_POOL_CREATE(timer_pool, struct ISCI_TIMER *, SCI_MAX_TIMERS);
+};
+
+struct ISCI_REQUEST
+{
+ SCI_CONTROLLER_HANDLE_T controller_handle;
+ SCI_REMOTE_DEVICE_HANDLE_T remote_device_handle;
+ bus_dma_tag_t dma_tag;
+ bus_dmamap_t dma_map;
+ SCI_PHYSICAL_ADDRESS physical_address;
+ struct callout timer;
+};
+
+struct ISCI_IO_REQUEST
+{
+ struct ISCI_REQUEST parent;
+ SCI_STATUS status;
+ SCI_IO_REQUEST_HANDLE_T sci_object;
+ union ccb *ccb;
+ uint32_t num_segments;
+ uint32_t current_sge_index;
+ bus_dma_segment_t *sge;
+};
+
+struct ISCI_TASK_REQUEST
+{
+ struct ISCI_REQUEST parent;
+ struct scsi_sense_data sense_data;
+ SCI_TASK_REQUEST_HANDLE_T sci_object;
+ union ccb *ccb;
+
+};
+
+struct ISCI_PCI_BAR {
+
+ bus_space_tag_t bus_tag;
+ bus_space_handle_t bus_handle;
+ int resource_id;
+ struct resource *resource;
+
+};
+
+/*
+ * One of these per allocated PCI device.
+ */
+struct isci_softc {
+
+ struct ISCI_PCI_BAR pci_bar[ISCI_NUM_PCI_BARS];
+ struct ISCI_CONTROLLER controllers[SCI_MAX_CONTROLLERS];
+ SCI_LIBRARY_HANDLE_T sci_library_handle;
+ void * sci_library_memory;
+ SCIC_CONTROLLER_HANDLER_METHODS_T handlers[4];
+ struct ISCI_INTERRUPT_INFO interrupt_info[4];
+ uint32_t controller_count;
+ uint32_t num_interrupts;
+ uint32_t coalesce_number;
+ uint32_t coalesce_timeout;
+ device_t device;
+ SCI_PCI_COMMON_HEADER_T pci_common_header;
+ BOOL oem_parameters_found;
+ struct intr_config_hook config_hook;
+};
+
+int isci_allocate_resources(device_t device);
+
+int isci_allocate_dma_buffer(device_t device, struct ISCI_MEMORY *memory);
+
+void isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device,
+ union ccb *ccb);
+
+/**
+ * Returns the negotiated link rate (in KB/s) for the associated
+ * remote device. Used to fill out bitrate field for GET_TRANS_SETTINGS.
+ * Will match the negotiated link rate for the lowest numbered local phy
+ * in the port/domain containing this remote device.
+ */
+uint32_t isci_remote_device_get_bitrate(
+ struct ISCI_REMOTE_DEVICE *remote_device);
+
+void isci_remote_device_freeze_lun_queue(
+ struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun);
+
+void isci_remote_device_release_lun_queue(
+ struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun);
+
+void isci_remote_device_release_device_queue(
+ struct ISCI_REMOTE_DEVICE * remote_device);
+
+void isci_request_construct(struct ISCI_REQUEST *request,
+ SCI_CONTROLLER_HANDLE_T scif_controller_handle,
+ bus_dma_tag_t io_buffer_dma_tag, bus_addr_t physical_address);
+
+#define isci_io_request_get_max_io_size() \
+ ((SCI_MAX_SCATTER_GATHER_ELEMENTS - 1) * PAGE_SIZE)
+
+#define isci_task_request_get_object_size() \
+ (sizeof(struct ISCI_TASK_REQUEST) + scif_task_request_get_object_size())
+
+#define isci_io_request_get_object_size() \
+ (sizeof(struct ISCI_IO_REQUEST) + scif_io_request_get_object_size())
+
+#define isci_request_get_object_size() \
+ max( \
+ isci_task_request_get_object_size(), \
+ isci_io_request_get_object_size() \
+ )
+
+
+void isci_io_request_execute_scsi_io(union ccb *ccb,
+ struct ISCI_CONTROLLER *controller);
+
+#if __FreeBSD_version >= 900026
+void isci_io_request_execute_smp_io(
+ union ccb *ccb, struct ISCI_CONTROLLER *controller);
+#endif
+
+void isci_io_request_timeout(void *);
+
+void isci_get_oem_parameters(struct isci_softc *isci);
+
+void isci_io_request_complete(
+ SCI_CONTROLLER_HANDLE_T scif_controller,
+ SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+ struct ISCI_IO_REQUEST * isci_request, SCI_IO_STATUS completion_status);
+
+void isci_task_request_complete(
+ SCI_CONTROLLER_HANDLE_T scif_controller,
+ SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+ SCI_TASK_REQUEST_HANDLE_T io_request, SCI_TASK_STATUS completion_status);
+
+void isci_sysctl_initialize(struct isci_softc *isci);
+
+void isci_controller_construct(struct ISCI_CONTROLLER *controller,
+ struct isci_softc *isci);
+
+SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller);
+
+int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller);
+
+void isci_controller_domain_discovery_complete(
+ struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain);
+
+int isci_controller_attach_to_cam(struct ISCI_CONTROLLER *controller);
+
+void isci_controller_start(void *controller);
+
+void isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index,
+ struct ISCI_CONTROLLER *controller);
+
+void isci_interrupt_setup(struct isci_softc *isci);
+void isci_interrupt_poll_handler(struct ISCI_CONTROLLER *controller);
+
+void isci_log_message(uint32_t verbosity, char *log_message_prefix,
+ char *log_message, ...);
+
+extern uint32_t g_isci_debug_level;
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_controller.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_controller.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,653 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <sys/conf.h>
+#include <sys/malloc.h>
+
+#include <dev/isci/scil/sci_memory_descriptor_list.h>
+#include <dev/isci/scil/sci_memory_descriptor_list_decorator.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_library.h>
+#include <dev/isci/scil/scif_io_request.h>
+#include <dev/isci/scil/scif_task_request.h>
+#include <dev/isci/scil/scif_remote_device.h>
+#include <dev/isci/scil/scif_domain.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+void isci_action(struct cam_sim *sim, union ccb *ccb);
+void isci_poll(struct cam_sim *sim);
+
+#define ccb_sim_ptr sim_priv.entries[0].ptr
+
+/**
+ * @brief This user callback will inform the user that the controller has
+ * had a serious unexpected error. The user should not the error,
+ * disable interrupts, and wait for current ongoing processing to
+ * complete. Subsequently, the user should reset the controller.
+ *
+ * @param[in] controller This parameter specifies the controller that had
+ * an error.
+ *
+ * @return none
+ */
+void scif_cb_controller_error(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_CONTROLLER_ERROR error)
+{
+
+ isci_log_message(0, "ISCI", "scif_cb_controller_error: 0x%x\n",
+ error);
+}
+
+/**
+ * @brief This user callback will inform the user that the controller has
+ * finished the start process.
+ *
+ * @param[in] controller This parameter specifies the controller that was
+ * started.
+ * @param[in] completion_status This parameter specifies the results of
+ * the start operation. SCI_SUCCESS indicates successful
+ * completion.
+ *
+ * @return none
+ */
+void scif_cb_controller_start_complete(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_STATUS completion_status)
+{
+ uint32_t index;
+ struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+ sci_object_get_association(controller);
+
+ isci_controller->is_started = TRUE;
+
+ /* Set bits for all domains. We will clear them one-by-one once
+ * the domains complete discovery, or return error when calling
+ * scif_domain_discover. Once all bits are clear, we will register
+ * the controller with CAM.
+ */
+ isci_controller->initial_discovery_mask = (1 << SCI_MAX_DOMAINS) - 1;
+
+ for(index = 0; index < SCI_MAX_DOMAINS; index++) {
+ SCI_STATUS status;
+ SCI_DOMAIN_HANDLE_T domain =
+ isci_controller->domain[index].sci_object;
+
+ status = scif_domain_discover(
+ domain,
+ scif_domain_get_suggested_discover_timeout(domain),
+ DEVICE_TIMEOUT
+ );
+
+ if (status != SCI_SUCCESS)
+ {
+ isci_controller_domain_discovery_complete(
+ isci_controller, &isci_controller->domain[index]);
+ }
+ }
+}
+
+/**
+ * @brief This user callback will inform the user that the controller has
+ * finished the stop process. Note, after user calls
+ * scif_controller_stop(), before user receives this controller stop
+ * complete callback, user should not expect any callback from
+ * framework, such like scif_cb_domain_change_notification().
+ *
+ * @param[in] controller This parameter specifies the controller that was
+ * stopped.
+ * @param[in] completion_status This parameter specifies the results of
+ * the stop operation. SCI_SUCCESS indicates successful
+ * completion.
+ *
+ * @return none
+ */
+void scif_cb_controller_stop_complete(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_STATUS completion_status)
+{
+ struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+ sci_object_get_association(controller);
+
+ isci_controller->is_started = FALSE;
+}
+
+/**
+ * @brief This method will be invoked to allocate memory dynamically.
+ *
+ * @param[in] controller This parameter represents the controller
+ * object for which to allocate memory.
+ * @param[out] mde This parameter represents the memory descriptor to
+ * be filled in by the user that will reference the newly
+ * allocated memory.
+ *
+ * @return none
+ */
+void scif_cb_controller_allocate_memory(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde)
+{
+
+}
+
+/**
+ * @brief This method will be invoked to allocate memory dynamically.
+ *
+ * @param[in] controller This parameter represents the controller
+ * object for which to allocate memory.
+ * @param[out] mde This parameter represents the memory descriptor to
+ * be filled in by the user that will reference the newly
+ * allocated memory.
+ *
+ * @return none
+ */
+void scif_cb_controller_free_memory(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_PHYSICAL_MEMORY_DESCRIPTOR_T * mde)
+{
+
+}
+
+void isci_controller_construct(struct ISCI_CONTROLLER *controller,
+ struct isci_softc *isci)
+{
+ SCI_CONTROLLER_HANDLE_T scif_controller_handle;
+
+ scif_library_allocate_controller(isci->sci_library_handle,
+ &scif_controller_handle);
+
+ scif_controller_construct(isci->sci_library_handle,
+ scif_controller_handle, NULL);
+
+ controller->isci = isci;
+ controller->scif_controller_handle = scif_controller_handle;
+
+ /* This allows us to later use
+ * sci_object_get_association(scif_controller_handle)
+ * inside of a callback routine to get our struct ISCI_CONTROLLER object
+ */
+ sci_object_set_association(scif_controller_handle, (void *)controller);
+
+ controller->is_started = FALSE;
+ controller->is_frozen = FALSE;
+ controller->sim = NULL;
+ controller->initial_discovery_mask = 0;
+
+ sci_fast_list_init(&controller->pending_device_reset_list);
+
+ mtx_init(&controller->lock, "isci", NULL, MTX_DEF);
+
+ uint32_t domain_index;
+
+ for(domain_index = 0; domain_index < SCI_MAX_DOMAINS; domain_index++) {
+ isci_domain_construct( &controller->domain[domain_index],
+ domain_index, controller);
+ }
+
+ controller->timer_memory = malloc(
+ sizeof(struct ISCI_TIMER) * SCI_MAX_TIMERS, M_ISCI,
+ M_NOWAIT | M_ZERO);
+
+ sci_pool_initialize(controller->timer_pool);
+
+ struct ISCI_TIMER *timer = (struct ISCI_TIMER *)
+ controller->timer_memory;
+
+ for ( int i = 0; i < SCI_MAX_TIMERS; i++ ) {
+ sci_pool_put(controller->timer_pool, timer++);
+ }
+}
+
+SCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller)
+{
+ SCIC_USER_PARAMETERS_T scic_user_parameters;
+ SCI_CONTROLLER_HANDLE_T scic_controller_handle;
+ unsigned long tunable;
+ int i;
+
+ scic_controller_handle =
+ scif_controller_get_scic_handle(controller->scif_controller_handle);
+
+ if (controller->isci->oem_parameters_found == TRUE)
+ {
+ scic_oem_parameters_set(
+ scic_controller_handle,
+ &controller->oem_parameters,
+ (uint8_t)(controller->oem_parameters_version));
+ }
+
+ scic_user_parameters_get(scic_controller_handle, &scic_user_parameters);
+
+ if (TUNABLE_ULONG_FETCH("hw.isci.no_outbound_task_timeout", &tunable))
+ scic_user_parameters.sds1.no_outbound_task_timeout =
+ (uint8_t)tunable;
+
+ if (TUNABLE_ULONG_FETCH("hw.isci.ssp_max_occupancy_timeout", &tunable))
+ scic_user_parameters.sds1.ssp_max_occupancy_timeout =
+ (uint16_t)tunable;
+
+ if (TUNABLE_ULONG_FETCH("hw.isci.stp_max_occupancy_timeout", &tunable))
+ scic_user_parameters.sds1.stp_max_occupancy_timeout =
+ (uint16_t)tunable;
+
+ if (TUNABLE_ULONG_FETCH("hw.isci.ssp_inactivity_timeout", &tunable))
+ scic_user_parameters.sds1.ssp_inactivity_timeout =
+ (uint16_t)tunable;
+
+ if (TUNABLE_ULONG_FETCH("hw.isci.stp_inactivity_timeout", &tunable))
+ scic_user_parameters.sds1.stp_inactivity_timeout =
+ (uint16_t)tunable;
+
+ if (TUNABLE_ULONG_FETCH("hw.isci.max_speed_generation", &tunable))
+ for (i = 0; i < SCI_MAX_PHYS; i++)
+ scic_user_parameters.sds1.phys[i].max_speed_generation =
+ (uint8_t)tunable;
+
+ scic_user_parameters_set(scic_controller_handle, &scic_user_parameters);
+
+ /* Scheduler bug in SCU requires SCIL to reserve some task contexts as a
+ * a workaround - one per domain.
+ */
+ controller->queue_depth = SCI_MAX_IO_REQUESTS - SCI_MAX_DOMAINS;
+
+ if (TUNABLE_INT_FETCH("hw.isci.controller_queue_depth",
+ &controller->queue_depth)) {
+ controller->queue_depth = max(1, min(controller->queue_depth,
+ SCI_MAX_IO_REQUESTS - SCI_MAX_DOMAINS));
+ }
+
+ /* Reserve one request so that we can ensure we have one available TC
+ * to do internal device resets.
+ */
+ controller->sim_queue_depth = controller->queue_depth - 1;
+
+ /* Although we save one TC to do internal device resets, it is possible
+ * we could end up using several TCs for simultaneous device resets
+ * while at the same time having CAM fill our controller queue. To
+ * simulate this condition, and how our driver handles it, we can set
+ * this io_shortage parameter, which will tell CAM that we have a
+ * large queue depth than we really do.
+ */
+ uint32_t io_shortage = 0;
+ TUNABLE_INT_FETCH("hw.isci.io_shortage", &io_shortage);
+ controller->sim_queue_depth += io_shortage;
+
+ return (scif_controller_initialize(controller->scif_controller_handle));
+}
+
+int isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller)
+{
+ int error;
+ device_t device = controller->isci->device;
+ uint32_t max_segment_size = isci_io_request_get_max_io_size();
+ uint32_t status = 0;
+ struct ISCI_MEMORY *uncached_controller_memory =
+ &controller->uncached_controller_memory;
+ struct ISCI_MEMORY *cached_controller_memory =
+ &controller->cached_controller_memory;
+ struct ISCI_MEMORY *request_memory =
+ &controller->request_memory;
+ POINTER_UINT virtual_address;
+ bus_addr_t physical_address;
+
+ controller->mdl = sci_controller_get_memory_descriptor_list_handle(
+ controller->scif_controller_handle);
+
+ uncached_controller_memory->size = sci_mdl_decorator_get_memory_size(
+ controller->mdl, SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS);
+
+ error = isci_allocate_dma_buffer(device, uncached_controller_memory);
+
+ if (error != 0)
+ return (error);
+
+ sci_mdl_decorator_assign_memory( controller->mdl,
+ SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS,
+ uncached_controller_memory->virtual_address,
+ uncached_controller_memory->physical_address);
+
+ cached_controller_memory->size = sci_mdl_decorator_get_memory_size(
+ controller->mdl,
+ SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS
+ );
+
+ error = isci_allocate_dma_buffer(device, cached_controller_memory);
+
+ if (error != 0)
+ return (error);
+
+ sci_mdl_decorator_assign_memory(controller->mdl,
+ SCI_MDE_ATTRIBUTE_CACHEABLE | SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS,
+ cached_controller_memory->virtual_address,
+ cached_controller_memory->physical_address);
+
+ request_memory->size =
+ controller->queue_depth * isci_io_request_get_object_size();
+
+ error = isci_allocate_dma_buffer(device, request_memory);
+
+ if (error != 0)
+ return (error);
+
+ /* For STP PIO testing, we want to ensure we can force multiple SGLs
+ * since this has been a problem area in SCIL. This tunable parameter
+ * will allow us to force DMA segments to a smaller size, ensuring
+ * that even if a physically contiguous buffer is attached to this
+ * I/O, the DMA subsystem will pass us multiple segments in our DMA
+ * load callback.
+ */
+ TUNABLE_INT_FETCH("hw.isci.max_segment_size", &max_segment_size);
+
+ /* Create DMA tag for our I/O requests. Then we can create DMA maps based off
+ * of this tag and store them in each of our ISCI_IO_REQUEST objects. This
+ * will enable better performance than creating the DMA maps everytime we get
+ * an I/O.
+ */
+ status = bus_dma_tag_create(bus_get_dma_tag(device), 0x1, 0x0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ isci_io_request_get_max_io_size(),
+ SCI_MAX_SCATTER_GATHER_ELEMENTS, max_segment_size, 0, NULL, NULL,
+ &controller->buffer_dma_tag);
+
+ sci_pool_initialize(controller->request_pool);
+
+ virtual_address = request_memory->virtual_address;
+ physical_address = request_memory->physical_address;
+
+ for (int i = 0; i < controller->queue_depth; i++) {
+ struct ISCI_REQUEST *request =
+ (struct ISCI_REQUEST *)virtual_address;
+
+ isci_request_construct(request,
+ controller->scif_controller_handle,
+ controller->buffer_dma_tag, physical_address);
+
+ sci_pool_put(controller->request_pool, request);
+
+ virtual_address += isci_request_get_object_size();
+ physical_address += isci_request_get_object_size();
+ }
+
+ uint32_t remote_device_size = sizeof(struct ISCI_REMOTE_DEVICE) +
+ scif_remote_device_get_object_size();
+
+ controller->remote_device_memory = (uint8_t *) malloc(
+ remote_device_size * SCI_MAX_REMOTE_DEVICES, M_ISCI,
+ M_NOWAIT | M_ZERO);
+
+ sci_pool_initialize(controller->remote_device_pool);
+
+ uint8_t *remote_device_memory_ptr = controller->remote_device_memory;
+
+ for (int i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
+ struct ISCI_REMOTE_DEVICE *remote_device =
+ (struct ISCI_REMOTE_DEVICE *)remote_device_memory_ptr;
+
+ controller->remote_device[i] = NULL;
+ remote_device->index = i;
+ remote_device->is_resetting = FALSE;
+ remote_device->frozen_lun_mask = 0;
+ sci_fast_list_element_init(remote_device,
+ &remote_device->pending_device_reset_element);
+ sci_pool_put(controller->remote_device_pool, remote_device);
+ remote_device_memory_ptr += remote_device_size;
+ }
+
+ return (0);
+}
+
+void isci_controller_start(void *controller_handle)
+{
+ struct ISCI_CONTROLLER *controller =
+ (struct ISCI_CONTROLLER *)controller_handle;
+ SCI_CONTROLLER_HANDLE_T scif_controller_handle =
+ controller->scif_controller_handle;
+
+ scif_controller_start(scif_controller_handle,
+ scif_controller_get_suggested_start_timeout(scif_controller_handle));
+
+ scic_controller_enable_interrupts(
+ scif_controller_get_scic_handle(controller->scif_controller_handle));
+}
+
+void isci_controller_domain_discovery_complete(
+ struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain)
+{
+ if (isci_controller->sim == NULL)
+ {
+ /* Controller has not been attached to CAM yet. We'll clear
+ * the discovery bit for this domain, then check if all bits
+ * are now clear. That would indicate that all domains are
+ * done with discovery and we can then attach the controller
+ * to CAM.
+ */
+
+ isci_controller->initial_discovery_mask &=
+ ~(1 << isci_domain->index);
+
+ if (isci_controller->initial_discovery_mask == 0) {
+ struct isci_softc *driver = isci_controller->isci;
+ uint8_t next_index = isci_controller->index + 1;
+
+ isci_controller_attach_to_cam(isci_controller);
+
+ if (next_index < driver->controller_count) {
+ /* There are more controllers that need to
+ * start. So start the next one.
+ */
+ isci_controller_start(
+ &driver->controllers[next_index]);
+ }
+ else
+ {
+ /* All controllers have been started and completed discovery.
+ * Disestablish the config hook while will signal to the
+ * kernel during boot that it is safe to try to find and
+ * mount the root partition.
+ */
+ config_intrhook_disestablish(
+ &driver->config_hook);
+ }
+ }
+ }
+}
+
+int isci_controller_attach_to_cam(struct ISCI_CONTROLLER *controller)
+{
+ struct isci_softc *isci = controller->isci;
+ device_t parent = device_get_parent(isci->device);
+ int unit = device_get_unit(isci->device);
+ struct cam_devq *isci_devq = cam_simq_alloc(controller->sim_queue_depth);
+
+ if(isci_devq == NULL) {
+ isci_log_message(0, "ISCI", "isci_devq is NULL \n");
+ return (-1);
+ }
+
+ controller->sim = cam_sim_alloc(isci_action, isci_poll, "isci",
+ controller, unit, &controller->lock, controller->sim_queue_depth,
+ controller->sim_queue_depth, isci_devq);
+
+ if(controller->sim == NULL) {
+ isci_log_message(0, "ISCI", "cam_sim_alloc... fails\n");
+ cam_simq_free(isci_devq);
+ return (-1);
+ }
+
+ if(xpt_bus_register(controller->sim, parent, controller->index)
+ != CAM_SUCCESS) {
+ isci_log_message(0, "ISCI", "xpt_bus_register...fails \n");
+ cam_sim_free(controller->sim, TRUE);
+ mtx_unlock(&controller->lock);
+ return (-1);
+ }
+
+ if(xpt_create_path(&controller->path, NULL,
+ cam_sim_path(controller->sim), CAM_TARGET_WILDCARD,
+ CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ isci_log_message(0, "ISCI", "xpt_create_path....fails\n");
+ xpt_bus_deregister(cam_sim_path(controller->sim));
+ cam_sim_free(controller->sim, TRUE);
+ mtx_unlock(&controller->lock);
+ return (-1);
+ }
+
+ return (0);
+}
+
+void isci_poll(struct cam_sim *sim)
+{
+ struct ISCI_CONTROLLER *controller =
+ (struct ISCI_CONTROLLER *)cam_sim_softc(sim);
+
+ isci_interrupt_poll_handler(controller);
+}
+
+void isci_action(struct cam_sim *sim, union ccb *ccb)
+{
+ struct ISCI_CONTROLLER *controller =
+ (struct ISCI_CONTROLLER *)cam_sim_softc(sim);
+
+ switch ( ccb->ccb_h.func_code ) {
+ case XPT_PATH_INQ:
+ {
+ struct ccb_pathinq *cpi = &ccb->cpi;
+ int bus = cam_sim_bus(sim);
+ ccb->ccb_h.ccb_sim_ptr = sim;
+ cpi->version_num = 1;
+ cpi->hba_inquiry = PI_TAG_ABLE;
+ cpi->target_sprt = 0;
+ cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN;
+ cpi->hba_eng_cnt = 0;
+ cpi->max_target = SCI_MAX_REMOTE_DEVICES - 1;
+ cpi->max_lun = ISCI_MAX_LUN;
+#if __FreeBSD_version >= 704100
+ cpi->maxio = isci_io_request_get_max_io_size();
+#endif
+ cpi->unit_number = cam_sim_unit(sim);
+ cpi->bus_id = bus;
+ cpi->initiator_id = SCI_MAX_REMOTE_DEVICES;
+ cpi->base_transfer_speed = 300000;
+ strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+ strncpy(cpi->hba_vid, "Intel Corp.", HBA_IDLEN);
+ strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+ cpi->transport = XPORT_SAS;
+ cpi->transport_version = 0;
+ cpi->protocol = PROTO_SCSI;
+ cpi->protocol_version = SCSI_REV_SPC2;
+ cpi->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ }
+ break;
+ case XPT_GET_TRAN_SETTINGS:
+ {
+ struct ccb_trans_settings *general_settings = &ccb->cts;
+ struct ccb_trans_settings_sas *sas_settings =
+ &general_settings->xport_specific.sas;
+ struct ccb_trans_settings_scsi *scsi_settings =
+ &general_settings->proto_specific.scsi;
+ struct ISCI_REMOTE_DEVICE *remote_device;
+
+ remote_device = controller->remote_device[ccb->ccb_h.target_id];
+
+ if (remote_device == NULL) {
+ ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ xpt_done(ccb);
+ break;
+ }
+
+ general_settings->protocol = PROTO_SCSI;
+ general_settings->transport = XPORT_SAS;
+ general_settings->protocol_version = SCSI_REV_SPC2;
+ general_settings->transport_version = 0;
+ scsi_settings->valid = CTS_SCSI_VALID_TQ;
+ scsi_settings->flags = CTS_SCSI_FLAGS_TAG_ENB;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+
+ sas_settings->bitrate =
+ isci_remote_device_get_bitrate(remote_device);
+
+ if (sas_settings->bitrate != 0)
+ sas_settings->valid = CTS_SAS_VALID_SPEED;
+
+ xpt_done(ccb);
+ }
+ break;
+ case XPT_SCSI_IO:
+ isci_io_request_execute_scsi_io(ccb, controller);
+ break;
+#if __FreeBSD_version >= 900026
+ case XPT_SMP_IO:
+ isci_io_request_execute_smp_io(ccb, controller);
+ break;
+#endif
+ case XPT_SET_TRAN_SETTINGS:
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ xpt_done(ccb);
+ break;
+ case XPT_CALC_GEOMETRY:
+ cam_calc_geometry(&ccb->ccg, /*extended*/1);
+ xpt_done(ccb);
+ break;
+ case XPT_RESET_DEV:
+ {
+ struct ISCI_REMOTE_DEVICE *remote_device =
+ controller->remote_device[ccb->ccb_h.target_id];
+
+ if (remote_device != NULL)
+ isci_remote_device_reset(remote_device, ccb);
+ else {
+ ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ xpt_done(ccb);
+ }
+ }
+ break;
+ case XPT_RESET_BUS:
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ xpt_done(ccb);
+ break;
+ default:
+ isci_log_message(0, "ISCI", "Unhandled func_code 0x%x\n",
+ ccb->ccb_h.func_code);
+ ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQ_INVALID;
+ xpt_done(ccb);
+ break;
+ }
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_domain.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_domain.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,318 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
+
+#include <dev/isci/scil/scif_domain.h>
+#include <dev/isci/scil/scif_remote_device.h>
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+/**
+ * @brief This callback method informs the framework user that something
+ * in the supplied domain has changed (e.g. a device was added or
+ * removed).
+ *
+ * This callback is called by the framework outside of discovery or
+ * target reset processes. Specifically, domain changes occurring
+ * during these processes are handled by the framework. For example,
+ * in the case of Serial Attached SCSI, reception of a BROADCAST (CHANGE)
+ * during discovery will cause discovery to restart. Thus, discovery
+ * does not complete until all BCNs are processed. Note, during controller
+ * stopping/reset process, the framework user should not expect this call
+ * back.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_change_notification(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain)
+{
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+
+ /* When the controller start is complete, we will explicitly discover
+ * all of the domains then. This is because SCIF will not allow
+ * any I/O to start until the controller is ready, meaning internal SMP
+ * requests triggered by domain discovery won't work until the controller
+ * is ready.
+ */
+ if (isci_controller->is_started == TRUE)
+ scif_domain_discover(domain,
+ scif_domain_get_suggested_discover_timeout(domain),
+ DEVICE_TIMEOUT);
+}
+
+/**
+ * @brief This callback method informs the framework user that a previously
+ * requested discovery operation on the domain has completed.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] completion_status This parameter indicates the results of the
+ * discovery operation.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_discovery_complete(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status)
+{
+
+ if(completion_status != SCI_SUCCESS)
+ isci_log_message(0, "ISCI",
+ "scif_cb_domain_discovery_complete status = 0x%x\n",
+ completion_status);
+
+ isci_controller_domain_discovery_complete(
+ (struct ISCI_CONTROLLER *)sci_object_get_association(controller),
+ (struct ISCI_DOMAIN *) sci_object_get_association(domain));
+}
+
+/**
+ * @brief This callback method informs the framework user that a previously
+ * requested reset operation on the domain has completed.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] completion_status This parameter indicates the results of the
+ * reset operation.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_reset_complete(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_STATUS completion_status)
+{
+
+}
+
+/**
+ * @brief This callback method informs the framework user that the domain
+ * is ready and capable of processing IO requests for devices found
+ * inside it.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_ready(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain)
+{
+ uint32_t i;
+ struct ISCI_DOMAIN *isci_domain = sci_object_get_association(domain);
+ struct ISCI_CONTROLLER *isci_controller =
+ sci_object_get_association(controller);
+
+ for (i = 0; i < SCI_MAX_REMOTE_DEVICES; i++) {
+ struct ISCI_REMOTE_DEVICE *remote_device =
+ isci_controller->remote_device[i];
+
+ if (remote_device != NULL &&
+ remote_device->domain == isci_domain)
+ isci_remote_device_release_device_queue(remote_device);
+ }
+}
+
+/**
+ * @brief This callback method informs the framework user that the domain
+ * is no longer ready. Thus, it is incapable of processing IO
+ * requests for devices found inside it.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_not_ready(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain)
+{
+
+}
+
+/**
+ * @brief This callback method informs the framework user that a new
+ * direct attached device was found in the domain.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] sas_address This parameter specifies the SAS address of
+ * the new device.
+ * @param[in] protocols This parameter specifies the protocols
+ * supported by the newly discovered device.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_da_device_added(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_SAS_ADDRESS_T *sas_address,
+ SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T *protocols)
+{
+ struct ISCI_REMOTE_DEVICE *remote_device;
+ struct ISCI_DOMAIN *isci_domain =
+ (struct ISCI_DOMAIN *)sci_object_get_association(domain);
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+
+ sci_pool_get(isci_controller->remote_device_pool, remote_device);
+
+ scif_remote_device_construct(domain,
+ (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE),
+ &(remote_device->sci_object));
+
+ sci_object_set_association(remote_device->sci_object, remote_device);
+
+ scif_remote_device_da_construct(remote_device->sci_object, sas_address,
+ protocols);
+
+ /* We do not put the device in the ISCI_CONTROLLER's device array yet.
+ * That will happen once the device becomes ready (see
+ * scif_cb_remote_device_ready).
+ */
+
+ remote_device->domain = isci_domain;
+}
+
+/**
+ * @brief This callback method informs the framework user that a new
+ * expander attached device was found in the domain.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] containing_device This parameter specifies the remote
+ * device that contains the device that was added.
+ * @param[in] smp_response This parameter specifies the SMP response
+ * data associated with the newly discovered device.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_ea_device_added(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T containing_device,
+ SMP_RESPONSE_DISCOVER_T *smp_response)
+{
+ struct ISCI_REMOTE_DEVICE *remote_device;
+ struct ISCI_DOMAIN *isci_domain =
+ (struct ISCI_DOMAIN *)sci_object_get_association(domain);
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+
+ sci_pool_get(isci_controller->remote_device_pool, remote_device);
+
+ scif_remote_device_construct( domain,
+ (uint8_t*)remote_device + sizeof(struct ISCI_REMOTE_DEVICE),
+ &(remote_device->sci_object));
+
+ sci_object_set_association(remote_device->sci_object, remote_device);
+
+ scif_remote_device_ea_construct(remote_device->sci_object,
+ containing_device, smp_response);
+
+ /* We do not put the device in the ISCI_CONTROLLER's device array yet.
+ * That will happen once the device becomes ready (see
+ * scif_cb_remote_device_ready).
+ */
+ remote_device->domain = isci_domain;
+}
+
+/**
+ * @brief This callback method informs the framework user that a device
+ * has been removed from the domain.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] remote_device This parameter specifies the device object with
+ * which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_domain_device_removed(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
+{
+ struct ISCI_REMOTE_DEVICE *isci_remote_device =
+ (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device);
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *)sci_object_get_association(controller);
+ uint32_t path = cam_sim_path(isci_controller->sim);
+ union ccb *ccb = xpt_alloc_ccb_nowait();
+
+ isci_controller->remote_device[isci_remote_device->index] = NULL;
+
+ xpt_create_path(&ccb->ccb_h.path, xpt_periph, path,
+ isci_remote_device->index, CAM_LUN_WILDCARD);
+
+ xpt_rescan(ccb);
+
+ scif_remote_device_destruct(remote_device);
+
+ sci_pool_put(isci_controller->remote_device_pool, isci_remote_device);
+}
+
+void
+isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index,
+ struct ISCI_CONTROLLER *controller)
+{
+
+ scif_controller_get_domain_handle( controller->scif_controller_handle,
+ domain_index, &domain->sci_object);
+
+ domain->index = domain_index;
+ domain->controller = controller;
+ sci_object_set_association(domain->sci_object, (void *)domain);
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_interrupt.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_interrupt.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,229 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/isci/scil/scif_controller.h>
+
+void isci_interrupt_legacy_handler(void *arg);
+void isci_interrupt_msix_handler(void *arg);
+
+static int
+isci_interrupt_setup_legacy(struct isci_softc *isci)
+{
+ struct ISCI_INTERRUPT_INFO *interrupt_info = &isci->interrupt_info[0];
+
+ isci->num_interrupts = 1;
+
+ scic_controller_get_handler_methods(SCIC_LEGACY_LINE_INTERRUPT_TYPE,
+ 0, &isci->handlers[0]);
+
+ interrupt_info->handlers = &isci->handlers[0];
+ interrupt_info->rid = 0;
+ interrupt_info->interrupt_target_handle = (void *)isci;
+
+ interrupt_info->res = bus_alloc_resource_any(isci->device, SYS_RES_IRQ,
+ &interrupt_info->rid, RF_SHAREABLE|RF_ACTIVE);
+
+ if (interrupt_info->res == NULL) {
+ isci_log_message(0, "ISCI", "bus_alloc_resource failed\n");
+ return (-1);
+ }
+
+ interrupt_info->tag = NULL;
+ if (bus_setup_intr(isci->device, interrupt_info->res,
+ INTR_TYPE_CAM | INTR_MPSAFE, NULL, isci_interrupt_legacy_handler,
+ interrupt_info, &interrupt_info->tag)) {
+ isci_log_message(0, "ISCI", "bus_setup_intr failed\n");
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+isci_interrupt_setup_msix(struct isci_softc *isci)
+{
+ uint32_t controller_index;
+
+ scic_controller_get_handler_methods(SCIC_MSIX_INTERRUPT_TYPE,
+ SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER, &isci->handlers[0]);
+
+ for (controller_index = 0; controller_index < isci->controller_count;
+ controller_index++) {
+ uint32_t msix_index;
+ uint8_t base_index = controller_index *
+ SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER;
+
+ for (msix_index = 0; msix_index < SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER;
+ msix_index++) {
+ struct ISCI_INTERRUPT_INFO *info =
+ &isci->interrupt_info[base_index+msix_index];
+
+ info->handlers = &isci->handlers[msix_index];
+ info->interrupt_target_handle =
+ &isci->controllers[controller_index];
+
+ info->rid = base_index+msix_index+1;
+
+ info->res = bus_alloc_resource_any(isci->device,
+ SYS_RES_IRQ, &info->rid, RF_ACTIVE);
+ if (info->res == NULL) {
+ isci_log_message(0, "ISCI",
+ "bus_alloc_resource failed\n");
+ return (-1);
+ }
+
+ info->tag = NULL;
+ if (bus_setup_intr(isci->device, info->res,
+ INTR_TYPE_CAM | INTR_MPSAFE, NULL,
+ isci_interrupt_msix_handler, info, &info->tag)) {
+ isci_log_message(0, "ISCI",
+ "bus_setup_intr failed\n");
+ return (-1);
+ }
+ }
+ }
+
+ return (0);
+}
+
+void
+isci_interrupt_setup(struct isci_softc *isci)
+{
+ uint8_t max_msix_messages = SCI_MAX_MSIX_MESSAGES_PER_CONTROLLER *
+ isci->controller_count;
+ BOOL use_msix = FALSE;
+ uint32_t force_legacy_interrupts = 0;
+
+ TUNABLE_INT_FETCH("hw.isci.force_legacy_interrupts",
+ &force_legacy_interrupts);
+
+ if (!force_legacy_interrupts &&
+ pci_msix_count(isci->device) >= max_msix_messages) {
+
+ isci->num_interrupts = max_msix_messages;
+ pci_alloc_msix(isci->device, &isci->num_interrupts);
+ if (isci->num_interrupts == max_msix_messages)
+ use_msix = TRUE;
+ }
+
+ if (use_msix == TRUE)
+ isci_interrupt_setup_msix(isci);
+ else
+ isci_interrupt_setup_legacy(isci);
+}
+
+void
+isci_interrupt_legacy_handler(void *arg)
+{
+ struct ISCI_INTERRUPT_INFO *interrupt_info =
+ (struct ISCI_INTERRUPT_INFO *)arg;
+ struct isci_softc *isci =
+ (struct isci_softc *)interrupt_info->interrupt_target_handle;
+ SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler;
+ SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
+ int index;
+
+ interrupt_handler = interrupt_info->handlers->interrupt_handler;
+ completion_handler = interrupt_info->handlers->completion_handler;
+
+ for (index = 0; index < isci->controller_count; index++) {
+ struct ISCI_CONTROLLER *controller = &isci->controllers[index];
+
+ /* If controller_count > 0, we will get interrupts here for
+ * controller 0 before controller 1 has even started. So
+ * we need to make sure we don't call the completion handler
+ * for a non-started controller.
+ */
+ if (controller->is_started == TRUE) {
+ SCI_CONTROLLER_HANDLE_T scic_controller_handle =
+ scif_controller_get_scic_handle(
+ controller->scif_controller_handle);
+
+ if (interrupt_handler(scic_controller_handle)) {
+ mtx_lock(&controller->lock);
+ completion_handler(scic_controller_handle);
+ mtx_unlock(&controller->lock);
+ }
+ }
+ }
+}
+
+void
+isci_interrupt_msix_handler(void *arg)
+{
+ struct ISCI_INTERRUPT_INFO *interrupt_info =
+ (struct ISCI_INTERRUPT_INFO *)arg;
+ struct ISCI_CONTROLLER *controller =
+ (struct ISCI_CONTROLLER *)interrupt_info->interrupt_target_handle;
+ SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler;
+ SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
+
+ interrupt_handler = interrupt_info->handlers->interrupt_handler;
+ completion_handler = interrupt_info->handlers->completion_handler;
+
+ SCI_CONTROLLER_HANDLE_T scic_controller_handle;
+
+ scic_controller_handle = scif_controller_get_scic_handle(
+ controller->scif_controller_handle);
+
+ if (interrupt_handler(scic_controller_handle)) {
+ mtx_lock(&controller->lock);
+ completion_handler(scic_controller_handle);
+ mtx_unlock(&controller->lock);
+ }
+}
+
+void
+isci_interrupt_poll_handler(struct ISCI_CONTROLLER *controller)
+{
+ SCI_CONTROLLER_HANDLE_T scic_controller =
+ scif_controller_get_scic_handle(controller->scif_controller_handle);
+ SCIC_CONTROLLER_HANDLER_METHODS_T handlers;
+
+ scic_controller_get_handler_methods(SCIC_NO_INTERRUPTS, 0x0, &handlers);
+
+ if(handlers.interrupt_handler(scic_controller) == TRUE) {
+ /* Do not acquire controller lock in this path. xpt
+ * poll routine will get called with this lock already
+ * held, so we can't acquire it again here. Other users
+ * of this function must acquire the lock explicitly
+ * before calling this handler.
+ */
+ handlers.completion_handler(scic_controller);
+ }
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_io_request.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_io_request.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,923 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_message.h>
+
+#include <dev/isci/scil/intel_sas.h>
+
+#include <dev/isci/scil/sci_util.h>
+
+#include <dev/isci/scil/scif_io_request.h>
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_remote_device.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+#include <dev/isci/scil/scic_io_request.h>
+#include <dev/isci/scil/scic_user_callback.h>
+
+/**
+ * @brief This user callback will inform the user that an IO request has
+ * completed.
+ *
+ * @param[in] controller This parameter specifies the controller on
+ * which the IO request is completing.
+ * @param[in] remote_device This parameter specifies the remote device on
+ * which this request is completing.
+ * @param[in] io_request This parameter specifies the IO request that has
+ * completed.
+ * @param[in] completion_status This parameter specifies the results of
+ * the IO request operation. SCI_IO_SUCCESS indicates
+ * successful completion.
+ *
+ * @return none
+ */
+void
+scif_cb_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
+ SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+ SCI_IO_REQUEST_HANDLE_T io_request, SCI_IO_STATUS completion_status)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)sci_object_get_association(io_request);
+
+ scif_controller_complete_io(scif_controller, remote_device, io_request);
+ isci_io_request_complete(scif_controller, remote_device, isci_request,
+ completion_status);
+}
+
+void
+isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
+ SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+ struct ISCI_IO_REQUEST *isci_request, SCI_IO_STATUS completion_status)
+{
+ struct ISCI_CONTROLLER *isci_controller;
+ struct ISCI_REMOTE_DEVICE *isci_remote_device;
+ union ccb *ccb;
+
+ isci_controller = (struct ISCI_CONTROLLER *) sci_object_get_association(scif_controller);
+ isci_remote_device =
+ (struct ISCI_REMOTE_DEVICE *) sci_object_get_association(remote_device);
+
+ ccb = isci_request->ccb;
+
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+
+ switch (completion_status) {
+ case SCI_IO_SUCCESS:
+ case SCI_IO_SUCCESS_COMPLETE_BEFORE_START:
+#if __FreeBSD_version >= 900026
+ if (ccb->ccb_h.func_code == XPT_SMP_IO) {
+ void *smp_response =
+ scif_io_request_get_response_iu_address(
+ isci_request->sci_object);
+
+ memcpy(ccb->smpio.smp_response, smp_response,
+ ccb->smpio.smp_response_len);
+ }
+#endif
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ break;
+
+ case SCI_IO_SUCCESS_IO_DONE_EARLY:
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ ccb->csio.resid = ccb->csio.dxfer_len -
+ scif_io_request_get_number_of_bytes_transferred(
+ isci_request->sci_object);
+ break;
+
+ case SCI_IO_FAILURE_RESPONSE_VALID:
+ {
+ SCI_SSP_RESPONSE_IU_T * response_buffer;
+ uint32_t sense_length;
+ int error_code, sense_key, asc, ascq;
+ struct ccb_scsiio *csio = &ccb->csio;
+
+ response_buffer = (SCI_SSP_RESPONSE_IU_T *)
+ scif_io_request_get_response_iu_address(
+ isci_request->sci_object);
+
+ sense_length = sci_ssp_get_sense_data_length(
+ response_buffer->sense_data_length);
+
+ sense_length = MIN(csio->sense_len, sense_length);
+
+ memcpy(&csio->sense_data, response_buffer->data, sense_length);
+
+ csio->sense_resid = csio->sense_len - sense_length;
+ csio->scsi_status = response_buffer->status;
+ ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
+ ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
+ scsi_extract_sense( &csio->sense_data, &error_code, &sense_key,
+ &asc, &ascq );
+ isci_log_message(1, "ISCI",
+ "isci: bus=%x target=%x lun=%x cdb[0]=%x status=%x key=%x asc=%x ascq=%x\n",
+ ccb->ccb_h.path_id, ccb->ccb_h.target_id,
+ ccb->ccb_h.target_lun, csio->cdb_io.cdb_bytes[0],
+ csio->scsi_status, sense_key, asc, ascq);
+ break;
+ }
+
+ case SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED:
+ isci_remote_device_reset(isci_remote_device, NULL);
+
+ /* drop through */
+ case SCI_IO_FAILURE_TERMINATED:
+ ccb->ccb_h.status |= CAM_REQ_TERMIO;
+ isci_log_message(1, "ISCI",
+ "isci: bus=%x target=%x lun=%x cdb[0]=%x terminated\n",
+ ccb->ccb_h.path_id, ccb->ccb_h.target_id,
+ ccb->ccb_h.target_lun, ccb->csio.cdb_io.cdb_bytes[0]);
+ break;
+
+ case SCI_IO_FAILURE_INVALID_STATE:
+ case SCI_IO_FAILURE_INSUFFICIENT_RESOURCES:
+ ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ isci_remote_device_freeze_lun_queue(isci_remote_device,
+ ccb->ccb_h.target_lun);
+ break;
+
+ case SCI_IO_FAILURE_INVALID_REMOTE_DEVICE:
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ break;
+
+ case SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE:
+ {
+ struct ccb_relsim ccb_relsim;
+ struct cam_path *path;
+
+ xpt_create_path(&path, NULL,
+ cam_sim_path(isci_controller->sim),
+ isci_remote_device->index, 0);
+
+ xpt_setup_ccb(&ccb_relsim.ccb_h, path, 5);
+ ccb_relsim.ccb_h.func_code = XPT_REL_SIMQ;
+ ccb_relsim.ccb_h.flags = CAM_DEV_QFREEZE;
+ ccb_relsim.release_flags = RELSIM_ADJUST_OPENINGS;
+ ccb_relsim.openings =
+ scif_remote_device_get_max_queue_depth(remote_device);
+ xpt_action((union ccb *)&ccb_relsim);
+ xpt_free_path(path);
+ ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ }
+ break;
+
+ case SCI_IO_FAILURE:
+ case SCI_IO_FAILURE_REQUIRES_SCSI_ABORT:
+ case SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL:
+ case SCI_IO_FAILURE_PROTOCOL_VIOLATION:
+ case SCI_IO_FAILURE_INVALID_PARAMETER_VALUE:
+ case SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR:
+ default:
+ isci_log_message(1, "ISCI",
+ "isci: bus=%x target=%x lun=%x cdb[0]=%x completion status=%x\n",
+ ccb->ccb_h.path_id, ccb->ccb_h.target_id,
+ ccb->ccb_h.target_lun, ccb->csio.cdb_io.cdb_bytes[0],
+ completion_status);
+ ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
+ break;
+ }
+
+ if (ccb->ccb_h.status != CAM_REQ_CMP) {
+ /* ccb will be completed with some type of non-success
+ * status. So temporarily freeze the queue until the
+ * upper layers can act on the status. The CAM_DEV_QFRZN
+ * flag will then release the queue after the status is
+ * acted upon.
+ */
+ ccb->ccb_h.status |= CAM_DEV_QFRZN;
+ xpt_freeze_devq(ccb->ccb_h.path, 1);
+ }
+
+ callout_stop(&isci_request->parent.timer);
+ bus_dmamap_sync(isci_request->parent.dma_tag,
+ isci_request->parent.dma_map,
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_unload(isci_request->parent.dma_tag,
+ isci_request->parent.dma_map);
+
+ if (isci_remote_device->frozen_lun_mask != 0 &&
+ !(ccb->ccb_h.status & CAM_REQUEUE_REQ))
+ isci_remote_device_release_device_queue(isci_remote_device);
+
+ xpt_done(ccb);
+ isci_request->ccb = NULL;
+
+ if (isci_controller->is_frozen == TRUE) {
+ isci_controller->is_frozen = FALSE;
+ xpt_release_simq(isci_controller->sim, TRUE);
+ }
+
+ sci_pool_put(isci_controller->request_pool,
+ (struct ISCI_REQUEST *)isci_request);
+}
+
+/**
+ * @brief This callback method asks the user to provide the physical
+ * address for the supplied virtual address when building an
+ * io request object.
+ *
+ * @param[in] controller This parameter is the core controller object
+ * handle.
+ * @param[in] io_request This parameter is the io request object handle
+ * for which the physical address is being requested.
+ * @param[in] virtual_address This paramter is the virtual address which
+ * is to be returned as a physical address.
+ * @param[out] physical_address The physical address for the supplied virtual
+ * address.
+ *
+ * @return None.
+ */
+void
+scic_cb_io_request_get_physical_address(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_IO_REQUEST_HANDLE_T io_request, void *virtual_address,
+ SCI_PHYSICAL_ADDRESS *physical_address)
+{
+ SCI_IO_REQUEST_HANDLE_T scif_request =
+ sci_object_get_association(io_request);
+ struct ISCI_REQUEST *isci_request =
+ sci_object_get_association(scif_request);
+
+ if(isci_request != NULL) {
+ /* isci_request is not NULL, meaning this is a request initiated
+ * by CAM or the isci layer (i.e. device reset for I/O
+ * timeout). Therefore we can calculate the physical address
+ * based on the address we stored in the struct ISCI_REQUEST
+ * object.
+ */
+ *physical_address = isci_request->physical_address +
+ (uintptr_t)virtual_address -
+ (uintptr_t)isci_request;
+ } else {
+ /* isci_request is NULL, meaning this is a request generated
+ * internally by SCIL (i.e. for SMP requests or NCQ error
+ * recovery). Therefore we calculate the physical address
+ * based on the controller's uncached controller memory buffer,
+ * since we know that this is what SCIL uses for internal
+ * framework requests.
+ */
+ SCI_CONTROLLER_HANDLE_T scif_controller =
+ (SCI_CONTROLLER_HANDLE_T) sci_object_get_association(controller);
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
+ U64 virt_addr_offset = (uintptr_t)virtual_address -
+ (U64)isci_controller->uncached_controller_memory.virtual_address;
+
+ *physical_address =
+ isci_controller->uncached_controller_memory.physical_address
+ + virt_addr_offset;
+ }
+}
+
+/**
+ * @brief This callback method asks the user to provide the address for
+ * the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the virtual address of the CDB.
+ */
+void *
+scif_cb_io_request_get_cdb_address(void * scif_user_io_request)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+ return (isci_request->ccb->csio.cdb_io.cdb_bytes);
+}
+
+/**
+ * @brief This callback method asks the user to provide the length of
+ * the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the length of the CDB.
+ */
+uint32_t
+scif_cb_io_request_get_cdb_length(void * scif_user_io_request)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+ return (isci_request->ccb->csio.cdb_len);
+}
+
+/**
+ * @brief This callback method asks the user to provide the Logical Unit (LUN)
+ * associated with this IO request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ * by the protocol standard (e.g. T10 SAS specification). Please
+ * refer to the transport command information unit description
+ * in the associated standard.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the LUN associated with this request.
+ */
+uint32_t
+scif_cb_io_request_get_lun(void * scif_user_io_request)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+ return (isci_request->ccb->ccb_h.target_lun);
+}
+
+/**
+ * @brief This callback method asks the user to provide the task attribute
+ * associated with this IO request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ * by the protocol standard (e.g. T10 SAS specification). Please
+ * refer to the transport command information unit description
+ * in the associated standard.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the task attribute associated with this
+ * IO request.
+ */
+uint32_t
+scif_cb_io_request_get_task_attribute(void * scif_user_io_request)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+ uint32_t task_attribute;
+
+ if((isci_request->ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0)
+ switch(isci_request->ccb->csio.tag_action) {
+ case MSG_HEAD_OF_Q_TAG:
+ task_attribute = SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE;
+ break;
+
+ case MSG_ORDERED_Q_TAG:
+ task_attribute = SCI_SAS_ORDERED_ATTRIBUTE;
+ break;
+
+ case MSG_ACA_TASK:
+ task_attribute = SCI_SAS_ACA_ATTRIBUTE;
+ break;
+
+ default:
+ task_attribute = SCI_SAS_SIMPLE_ATTRIBUTE;
+ break;
+ }
+ else
+ task_attribute = SCI_SAS_SIMPLE_ATTRIBUTE;
+
+ return (task_attribute);
+}
+
+/**
+ * @brief This callback method asks the user to provide the command priority
+ * associated with this IO request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ * by the protocol standard (e.g. T10 SAS specification). Please
+ * refer to the transport command information unit description
+ * in the associated standard.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the command priority associated with this
+ * IO request.
+ */
+uint32_t
+scif_cb_io_request_get_command_priority(void * scif_user_io_request)
+{
+ return (0);
+}
+
+/**
+ * @brief This method simply returns the virtual address associated
+ * with the scsi_io and byte_offset supplied parameters.
+ *
+ * @note This callback is not utilized in the fast path. The expectation
+ * is that this method is utilized for items such as SCSI to ATA
+ * translation for commands like INQUIRY, READ CAPACITY, etc.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ * @param[in] byte_offset This parameter specifies the offset into the data
+ * buffers pointed to by the SGL. The byte offset starts at 0
+ * and continues until the last byte pointed to be the last SGL
+ * element.
+ *
+ * @return A virtual address pointer to the location specified by the
+ * parameters.
+ */
+uint8_t *
+scif_cb_io_request_get_virtual_address_from_sgl(void * scif_user_io_request,
+ uint32_t byte_offset)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+ return (isci_request->ccb->csio.data_ptr + byte_offset);
+}
+
+/**
+ * @brief This callback method asks the user to provide the number of
+ * bytes to be transfered as part of this request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the number of payload data bytes to be
+ * transfered for this IO request.
+ */
+uint32_t
+scif_cb_io_request_get_transfer_length(void * scif_user_io_request)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+ return (isci_request->ccb->csio.dxfer_len);
+
+}
+
+/**
+ * @brief This callback method asks the user to provide the data direction
+ * for this request.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the value of SCI_IO_REQUEST_DATA_OUT,
+ * SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
+ */
+SCI_IO_REQUEST_DATA_DIRECTION
+scif_cb_io_request_get_data_direction(void * scif_user_io_request)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+ switch (isci_request->ccb->ccb_h.flags & CAM_DIR_MASK) {
+ case CAM_DIR_IN:
+ return (SCI_IO_REQUEST_DATA_IN);
+ case CAM_DIR_OUT:
+ return (SCI_IO_REQUEST_DATA_OUT);
+ default:
+ return (SCI_IO_REQUEST_NO_DATA);
+ }
+}
+
+/**
+ * @brief This callback method asks the user to provide the address
+ * to where the next Scatter-Gather Element is located.
+ *
+ * Details regarding usage:
+ * - Regarding the first SGE: the user should initialize an index,
+ * or a pointer, prior to construction of the request that will
+ * reference the very first scatter-gather element. This is
+ * important since this method is called for every scatter-gather
+ * element, including the first element.
+ * - Regarding the last SGE: the user should return NULL from this
+ * method when this method is called and the SGL has exhausted
+ * all elements.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ * @param[in] current_sge_address This parameter specifies the address for
+ * the current SGE (i.e. the one that has just processed).
+ * @param[out] next_sge An address specifying the location for the next scatter
+ * gather element to be processed.
+ *
+ * @return None.
+ */
+void
+scif_cb_io_request_get_next_sge(void * scif_user_io_request,
+ void * current_sge_address, void ** next_sge)
+{
+ struct ISCI_IO_REQUEST *isci_request =
+ (struct ISCI_IO_REQUEST *)scif_user_io_request;
+
+ if (isci_request->current_sge_index == isci_request->num_segments)
+ *next_sge = NULL;
+ else {
+ bus_dma_segment_t *sge =
+ &isci_request->sge[isci_request->current_sge_index];
+
+ isci_request->current_sge_index++;
+ *next_sge = sge;
+ }
+}
+
+/**
+ * @brief This callback method asks the user to provide the contents of the
+ * "address" field in the Scatter-Gather Element.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ * @param[in] sge_address This parameter specifies the address for the
+ * SGE from which to retrieve the address field.
+ *
+ * @return A physical address specifying the contents of the SGE's address
+ * field.
+ */
+SCI_PHYSICAL_ADDRESS
+scif_cb_sge_get_address_field(void *scif_user_io_request, void *sge_address)
+{
+ bus_dma_segment_t *sge = (bus_dma_segment_t *)sge_address;
+
+ return ((SCI_PHYSICAL_ADDRESS)sge->ds_addr);
+}
+
+/**
+ * @brief This callback method asks the user to provide the contents of the
+ * "length" field in the Scatter-Gather Element.
+ *
+ * @param[in] scif_user_io_request This parameter points to the user's
+ * IO request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ * @param[in] sge_address This parameter specifies the address for the
+ * SGE from which to retrieve the address field.
+ *
+ * @return This method returns the length field specified inside the SGE
+ * referenced by the sge_address parameter.
+ */
+uint32_t
+scif_cb_sge_get_length_field(void *scif_user_io_request, void *sge_address)
+{
+ bus_dma_segment_t *sge = (bus_dma_segment_t *)sge_address;
+
+ return ((uint32_t)sge->ds_len);
+}
+
+void
+isci_request_construct(struct ISCI_REQUEST *request,
+ SCI_CONTROLLER_HANDLE_T scif_controller_handle,
+ bus_dma_tag_t io_buffer_dma_tag, bus_addr_t physical_address)
+{
+
+ request->controller_handle = scif_controller_handle;
+ request->dma_tag = io_buffer_dma_tag;
+ request->physical_address = physical_address;
+ bus_dmamap_create(request->dma_tag, 0, &request->dma_map);
+ callout_init(&request->timer, CALLOUT_MPSAFE);
+}
+
+static void
+isci_io_request_construct(void *arg, bus_dma_segment_t *seg, int nseg,
+ int error)
+{
+ union ccb *ccb;
+ struct ISCI_IO_REQUEST *io_request = (struct ISCI_IO_REQUEST *)arg;
+ SCI_REMOTE_DEVICE_HANDLE_T *device = io_request->parent.remote_device_handle;
+ SCI_STATUS status;
+
+ io_request->num_segments = nseg;
+ io_request->sge = seg;
+ ccb = io_request->ccb;
+
+ /* XXX More cleanup is needed here */
+ if ((nseg == 0) || (error != 0)) {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ return;
+ }
+
+ io_request->status = scif_io_request_construct(
+ io_request->parent.controller_handle,
+ io_request->parent.remote_device_handle,
+ SCI_CONTROLLER_INVALID_IO_TAG, (void *)io_request,
+ (void *)((char*)io_request + sizeof(struct ISCI_IO_REQUEST)),
+ &io_request->sci_object);
+
+ if (io_request->status != SCI_SUCCESS) {
+ isci_io_request_complete(io_request->parent.controller_handle,
+ device, io_request, io_request->status);
+ return;
+ }
+
+ sci_object_set_association(io_request->sci_object, io_request);
+
+ bus_dmamap_sync(io_request->parent.dma_tag, io_request->parent.dma_map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ status = (SCI_STATUS)scif_controller_start_io(
+ io_request->parent.controller_handle, device,
+ io_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);
+
+ if (status != SCI_SUCCESS) {
+ isci_io_request_complete(io_request->parent.controller_handle,
+ device, io_request, status);
+ return;
+ }
+
+ if (ccb->ccb_h.timeout != CAM_TIME_INFINITY)
+ callout_reset(&io_request->parent.timer, ccb->ccb_h.timeout,
+ isci_io_request_timeout, io_request);
+}
+
+void
+isci_io_request_execute_scsi_io(union ccb *ccb,
+ struct ISCI_CONTROLLER *controller)
+{
+ struct ccb_scsiio *csio = &ccb->csio;
+ target_id_t target_id = ccb->ccb_h.target_id;
+ struct ISCI_REQUEST *request;
+ struct ISCI_IO_REQUEST *io_request;
+ struct ISCI_REMOTE_DEVICE *device =
+ controller->remote_device[target_id];
+ int error;
+
+ if (device == NULL) {
+ ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ xpt_done(ccb);
+ return;
+ }
+
+ if (sci_pool_empty(controller->request_pool)) {
+ ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ xpt_freeze_simq(controller->sim, 1);
+ controller->is_frozen = TRUE;
+ xpt_done(ccb);
+ return;
+ }
+
+ ASSERT(device->is_resetting == FALSE);
+
+ sci_pool_get(controller->request_pool, request);
+ io_request = (struct ISCI_IO_REQUEST *)request;
+
+ io_request->ccb = ccb;
+ io_request->current_sge_index = 0;
+ io_request->parent.remote_device_handle = device->sci_object;
+
+ if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) != 0)
+ panic("Unexpected CAM_SCATTER_VALID flag! flags = 0x%x\n",
+ ccb->ccb_h.flags);
+
+ if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
+ panic("Unexpected CAM_DATA_PHYS flag! flags = 0x%x\n",
+ ccb->ccb_h.flags);
+
+ error = bus_dmamap_load(io_request->parent.dma_tag,
+ io_request->parent.dma_map, csio->data_ptr, csio->dxfer_len,
+ isci_io_request_construct, io_request, 0x0);
+
+ /* A resource shortage from BUSDMA will be automatically
+ * continued at a later point, pushing the CCB processing
+ * forward, which will in turn unfreeze the simq.
+ */
+ if (error == EINPROGRESS) {
+ xpt_freeze_simq(controller->sim, 1);
+ ccb->ccb_h.flags |= CAM_RELEASE_SIMQ;
+ }
+}
+
+void
+isci_io_request_timeout(void *arg)
+{
+ struct ISCI_IO_REQUEST *request = (struct ISCI_IO_REQUEST *)arg;
+ struct ISCI_REMOTE_DEVICE *remote_device = (struct ISCI_REMOTE_DEVICE *)
+ sci_object_get_association(request->parent.remote_device_handle);
+ struct ISCI_CONTROLLER *controller = remote_device->domain->controller;
+
+ mtx_lock(&controller->lock);
+ isci_remote_device_reset(remote_device, NULL);
+ mtx_unlock(&controller->lock);
+}
+
+#if __FreeBSD_version >= 900026
+/**
+ * @brief This callback method gets the size of and pointer to the buffer
+ * (if any) containing the request buffer for an SMP request.
+ *
+ * @param[in] core_request This parameter specifies the SCI core's request
+ * object associated with the SMP request.
+ * @param[out] smp_request_buffer This parameter returns a pointer to the
+ * payload portion of the SMP request - i.e. everything after
+ * the SMP request header.
+ *
+ * @return Size of the request buffer in bytes. This does *not* include
+ * the size of the SMP request header.
+ */
+static uint32_t
+smp_io_request_cb_get_request_buffer(SCI_IO_REQUEST_HANDLE_T core_request,
+ uint8_t ** smp_request_buffer)
+{
+ struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+ sci_object_get_association(sci_object_get_association(core_request));
+
+ *smp_request_buffer = isci_request->ccb->smpio.smp_request +
+ sizeof(SMP_REQUEST_HEADER_T);
+
+ return (isci_request->ccb->smpio.smp_request_len -
+ sizeof(SMP_REQUEST_HEADER_T));
+}
+
+/**
+ * @brief This callback method gets the SMP function for an SMP request.
+ *
+ * @param[in] core_request This parameter specifies the SCI core's request
+ * object associated with the SMP request.
+ *
+ * @return SMP function for the SMP request.
+ */
+static uint8_t
+smp_io_request_cb_get_function(SCI_IO_REQUEST_HANDLE_T core_request)
+{
+ struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+ sci_object_get_association(sci_object_get_association(core_request));
+ SMP_REQUEST_HEADER_T *header =
+ (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;
+
+ return (header->function);
+}
+
+/**
+ * @brief This callback method gets the SMP frame type for an SMP request.
+ *
+ * @param[in] core_request This parameter specifies the SCI core's request
+ * object associated with the SMP request.
+ *
+ * @return SMP frame type for the SMP request.
+ */
+static uint8_t
+smp_io_request_cb_get_frame_type(SCI_IO_REQUEST_HANDLE_T core_request)
+{
+ struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+ sci_object_get_association(sci_object_get_association(core_request));
+ SMP_REQUEST_HEADER_T *header =
+ (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;
+
+ return (header->smp_frame_type);
+}
+
+/**
+ * @brief This callback method gets the allocated response length for an SMP request.
+ *
+ * @param[in] core_request This parameter specifies the SCI core's request
+ * object associated with the SMP request.
+ *
+ * @return Allocated response length for the SMP request.
+ */
+static uint8_t
+smp_io_request_cb_get_allocated_response_length(
+ SCI_IO_REQUEST_HANDLE_T core_request)
+{
+ struct ISCI_IO_REQUEST *isci_request = (struct ISCI_IO_REQUEST *)
+ sci_object_get_association(sci_object_get_association(core_request));
+ SMP_REQUEST_HEADER_T *header =
+ (SMP_REQUEST_HEADER_T *)isci_request->ccb->smpio.smp_request;
+
+ return (header->allocated_response_length);
+}
+
+static SCI_STATUS
+isci_smp_request_construct(struct ISCI_IO_REQUEST *request)
+{
+ SCI_STATUS status;
+ SCIC_SMP_PASSTHRU_REQUEST_CALLBACKS_T callbacks;
+
+ status = scif_request_construct(request->parent.controller_handle,
+ request->parent.remote_device_handle, SCI_CONTROLLER_INVALID_IO_TAG,
+ (void *)request,
+ (void *)((char*)request + sizeof(struct ISCI_IO_REQUEST)),
+ &request->sci_object);
+
+ if (status == SCI_SUCCESS) {
+ callbacks.scic_cb_smp_passthru_get_request =
+ &smp_io_request_cb_get_request_buffer;
+ callbacks.scic_cb_smp_passthru_get_function =
+ &smp_io_request_cb_get_function;
+ callbacks.scic_cb_smp_passthru_get_frame_type =
+ &smp_io_request_cb_get_frame_type;
+ callbacks.scic_cb_smp_passthru_get_allocated_response_length =
+ &smp_io_request_cb_get_allocated_response_length;
+
+ /* create the smp passthrough part of the io request */
+ status = scic_io_request_construct_smp_pass_through(
+ scif_io_request_get_scic_handle(request->sci_object),
+ &callbacks);
+ }
+
+ return (status);
+}
+
+void
+isci_io_request_execute_smp_io(union ccb *ccb,
+ struct ISCI_CONTROLLER *controller)
+{
+ SCI_STATUS status;
+ target_id_t target_id = ccb->ccb_h.target_id;
+ struct ISCI_REQUEST *request;
+ struct ISCI_IO_REQUEST *io_request;
+ SCI_REMOTE_DEVICE_HANDLE_T smp_device_handle;
+ struct ISCI_REMOTE_DEVICE *end_device = controller->remote_device[target_id];
+
+ /* SMP commands are sent to an end device, because SMP devices are not
+ * exposed to the kernel. It is our responsibility to use this method
+ * to get the SMP device that contains the specified end device. If
+ * the device is direct-attached, the handle will come back NULL, and
+ * we'll just fail the SMP_IO with DEV_NOT_THERE.
+ */
+ scif_remote_device_get_containing_device(end_device->sci_object,
+ &smp_device_handle);
+
+ if (smp_device_handle == NULL) {
+ ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+ xpt_done(ccb);
+ return;
+ }
+
+ if (sci_pool_empty(controller->request_pool)) {
+ ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ xpt_freeze_simq(controller->sim, 1);
+ controller->is_frozen = TRUE;
+ xpt_done(ccb);
+ return;
+ }
+
+ ASSERT(device->is_resetting == FALSE);
+
+ sci_pool_get(controller->request_pool, request);
+ io_request = (struct ISCI_IO_REQUEST *)request;
+
+ io_request->ccb = ccb;
+ io_request->parent.remote_device_handle = smp_device_handle;
+
+ status = isci_smp_request_construct(io_request);
+
+ if (status != SCI_SUCCESS) {
+ isci_io_request_complete(controller->scif_controller_handle,
+ smp_device_handle, io_request, status);
+ return;
+ }
+
+ sci_object_set_association(io_request->sci_object, io_request);
+
+ status = (SCI_STATUS) scif_controller_start_io(
+ controller->scif_controller_handle, smp_device_handle,
+ io_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);
+
+ if (status != SCI_SUCCESS) {
+ isci_io_request_complete(controller->scif_controller_handle,
+ smp_device_handle, io_request, status);
+ return;
+ }
+
+ if (ccb->ccb_h.timeout != CAM_TIME_INFINITY)
+ callout_reset(&io_request->parent.timer, ccb->ccb_h.timeout,
+ isci_io_request_timeout, request);
+}
+#endif
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_logger.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_logger.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,351 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/isci/scil/scif_user_callback.h>
+#include <dev/isci/scil/scic_user_callback.h>
+#include <dev/isci/scil/sci_logger.h>
+
+#include <machine/stdarg.h>
+#include <sys/time.h>
+
+#define ERROR_LEVEL 0
+#define WARNING_LEVEL 1
+#define TRACE_LEVEL 2
+#define INFO_LEVEL 3
+
+void
+isci_log_message(uint32_t verbosity, char *log_message_prefix,
+ char *log_message, ...)
+{
+ va_list argp;
+ char buffer[512];
+ struct timeval tv;
+
+ if (verbosity > g_isci_debug_level)
+ return;
+
+ va_start (argp, log_message);
+ vsnprintf(buffer, sizeof(buffer)-1, log_message, argp);
+ va_end(argp);
+ microtime(&tv);
+
+ printf("isci: %d:%06d %s %s", (int)tv.tv_sec, (int)tv.tv_usec,
+ log_message_prefix, buffer);
+}
+
+
+#ifdef SCI_LOGGING
+#define SCI_ENABLE_LOGGING_ERROR 1
+#define SCI_ENABLE_LOGGING_WARNING 1
+#define SCI_ENABLE_LOGGING_INFO 1
+#define SCI_ENABLE_LOGGING_TRACE 1
+#define SCI_ENABLE_LOGGING_STATES 1
+
+#define ISCI_LOG_MESSAGE( \
+ logger_object, \
+ log_object_mask, \
+ log_message, \
+ verbosity, \
+ log_message_prefix \
+) \
+{ \
+ va_list argp; \
+ char buffer[512]; \
+ \
+ if (!sci_logger_is_enabled(logger_object, log_object_mask, verbosity)) \
+ return; \
+ \
+ va_start (argp, log_message); \
+ vsnprintf(buffer, sizeof(buffer)-1, log_message, argp); \
+ va_end(argp); \
+ \
+ /* prepend the "object:verbosity_level:" */ \
+ isci_log_message(verbosity, log_message_prefix, buffer); \
+}
+#endif /* SCI_LOGGING */
+
+
+#ifdef SCI_ENABLE_LOGGING_ERROR
+/**
+ * @brief In this method the user is expected to log the supplied
+ * error information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is an error from the framework.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void scif_cb_logger_log_error(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_ERROR, "FRAMEWORK: ERROR: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_WARNING
+/**
+ * @brief In this method the user is expected to log the supplied warning
+ * information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a warning from the framework.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_warning(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_WARNING, "FRAMEWORK: WARNING: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_INFO
+/**
+ * @brief In this method the user is expected to log the supplied debug
+ * information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a debug message from the framework.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_info(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_INFO, "FRAMEWORK: INFO: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_TRACE
+/**
+ * @brief In this method the user is expected to log the supplied function
+ * trace information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a function trace (i.e. entry/exit) message from the
+ * framework.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_trace(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_TRACE, "FRAMEWORK: TRACE: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_STATES
+/**
+ * @brief In this method the user is expected to log the supplied function
+ * state transition information. The user must be capable of handling
+ * variable length argument lists and should consider prepending the
+ * fact that this is a function trace (i.e. entry/exit) message from
+ * the framework.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scif_cb_logger_log_states(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_STATES, "FRAMEWORK: STATE TRANSITION: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_ERROR
+/**
+ * @brief In this method the user is expected to log the supplied
+ * error information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is an error from the core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_error(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_ERROR, "CORE: ERROR: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_WARNING
+/**
+ * @brief In this method the user is expected to log the supplied warning
+ * information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a warning from the core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_warning(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_WARNING, "CORE: WARNING: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_INFO
+/**
+ * @brief In this method the user is expected to log the supplied debug
+ * information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a debug message from the core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_info(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_INFO, "CORE: INFO: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_TRACE
+/**
+ * @brief In this method the user is expected to log the supplied function
+ * trace information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a function trace (i.e. entry/exit) message from the
+ * core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_trace(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_TRACE, "CORE: TRACE: ");
+}
+#endif
+
+#ifdef SCI_ENABLE_LOGGING_STATES
+/**
+ * @brief In this method the user is expected to log the supplied function
+ * state transition information. The user must be capable of handling
+ * variable length argument lists and should consider prepending the
+ * fact that this is a function trace (i.e. entry/exit) message from
+ * the core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void
+scic_cb_logger_log_states(SCI_LOGGER_HANDLE_T logger_object,
+ uint32_t log_object_mask, char *log_message, ...)
+{
+
+ ISCI_LOG_MESSAGE(logger_object, log_object_mask, log_message,
+ SCI_LOG_VERBOSITY_STATES, "CORE: STATE TRANSITION: ");
+}
+#endif
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_oem_parameters.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_oem_parameters.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,176 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/pmap.h>
+#include <machine/vmparam.h>
+#include <machine/pc/bios.h>
+#include <dev/isci/scil/scu_bios_definitions.h>
+
+struct pcir_header
+{
+ uint32_t signature;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t reserved;
+ uint16_t struct_length;
+ uint8_t struct_revision;
+ uint8_t cc_interface;
+ uint8_t cc_subclass;
+ uint8_t cc_baseclass;
+ uint16_t image_length;
+ uint16_t code_revision;
+ uint8_t code_type;
+ uint8_t indicator;
+ uint16_t reserved1;
+};
+
+struct rom_header
+{
+ uint8_t signature_byte[2];
+ uint8_t rom_length;
+ uint8_t jmp_code;
+ uint16_t entry_address;
+ uint8_t reserved[0x12];
+ uint16_t pcir_pointer;
+ uint16_t pnp_pointer;
+};
+
+struct oem_parameters_table
+{
+ uint8_t signature[4]; /* "$OEM" */
+ struct revision
+ {
+ uint16_t major:8; /* bits [7:0] */
+ uint16_t minor:8; /* bits [8:15] */
+ } revision;
+
+ uint16_t length;
+ uint8_t checksum;
+ uint8_t reserved1;
+ uint16_t reserved2;
+ uint8_t data[1];
+};
+
+void
+isci_get_oem_parameters(struct isci_softc *isci)
+{
+ uint32_t OROM_PHYSICAL_ADDRESS_START = 0xC0000;
+ uint32_t OROM_SEARCH_LENGTH = 0x30000;
+ uint16_t OROM_SIGNATURE = 0xAA55;
+ uint32_t OROM_SIZE = 512;
+ uint8_t *orom_start =
+ (uint8_t *)BIOS_PADDRTOVADDR(OROM_PHYSICAL_ADDRESS_START);
+ uint32_t offset = 0;
+
+ while (offset < OROM_SEARCH_LENGTH) {
+
+ /* Look for the OROM signature at the beginning of every
+ * 512-byte block in the OROM region
+ */
+ if (*(uint16_t*)(orom_start + offset) == OROM_SIGNATURE) {
+ uint32_t *rom;
+ struct rom_header *rom_header;
+ struct pcir_header *pcir_header;
+ uint16_t vendor_id = isci->pci_common_header.vendor_id;
+ uint16_t device_id = isci->pci_common_header.device_id;
+
+ rom = (uint32_t *)(orom_start + offset);
+ rom_header = (struct rom_header *)rom;
+ pcir_header = (struct pcir_header *)
+ ((uint8_t*)rom + rom_header->pcir_pointer);
+
+ /* OROM signature was found. Now check if the PCI
+ * device and vendor IDs match.
+ */
+ if (pcir_header->vendor_id == vendor_id &&
+ pcir_header->device_id == device_id)
+ {
+ /* OROM for this PCI device was found. Search
+ * this 512-byte block for the $OEM string,
+ * which will mark the beginning of the OEM
+ * parameter block.
+ */
+ uint8_t oem_sig[4] = {'$', 'O', 'E', 'M'};
+ int dword_index;
+
+ for (dword_index = 0;
+ dword_index < OROM_SIZE/sizeof(uint32_t);
+ dword_index++)
+ if (rom[dword_index] == *(uint32_t *)oem_sig) {
+ /* $OEM signature string was found. Now copy the OEM parameter block
+ * into the struct ISCI_CONTROLLER objects. After the controllers are
+ * constructed, we will pass this OEM parameter data to the SCI core
+ * controller.
+ */
+ struct oem_parameters_table *oem =
+ (struct oem_parameters_table *)&rom[dword_index];
+ SCI_BIOS_OEM_PARAM_BLOCK_T *oem_data =
+ (SCI_BIOS_OEM_PARAM_BLOCK_T *)oem->data;
+ int index;
+
+ isci->oem_parameters_found = TRUE;
+ isci_log_message(1, "ISCI", "oem_data->header.num_elements = %d\n",
+ oem_data->header.num_elements);
+
+ for (index = 0; index < oem_data->header.num_elements; index++)
+ {
+ memcpy(&isci->controllers[index].oem_parameters.sds1,
+ &oem_data->controller_element[index],
+ sizeof(SCIC_SDS_OEM_PARAMETERS_T));
+
+ isci_log_message(1, "ISCI", "OEM Parameter Data for controller %d\n",
+ index);
+
+ for (int i = 0; i < sizeof(SCIC_SDS_OEM_PARAMETERS_T); i++) {
+ uint8_t val = ((uint8_t *)&oem_data->controller_element[index])[i];
+ isci_log_message(1, "ISCI", "%02x ", val);
+ }
+ isci_log_message(1, "ISCI", "\n");
+ isci->controllers[index].oem_parameters_version = oem_data->header.version;
+ }
+ }
+
+ /* No need to continue searching for another
+ * OROM that matches this PCI device, so return
+ * immediately.
+ */
+ return;
+ }
+ }
+
+ offset += OROM_SIZE;
+ }
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_remote_device.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_remote_device.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,298 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
+
+#include <dev/isci/scil/scif_task_request.h>
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_domain.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+#include <dev/isci/scil/scic_port.h>
+#include <dev/isci/scil/scic_phy.h>
+
+/**
+ * @brief This callback method informs the framework user that the remote
+ * device is ready and capable of processing IO requests.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] remote_device This parameter specifies the device object with
+ * which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_remote_device_ready(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
+{
+ struct ISCI_REMOTE_DEVICE *isci_remote_device =
+ sci_object_get_association(remote_device);
+ struct ISCI_CONTROLLER *isci_controller =
+ sci_object_get_association(controller);
+ uint32_t device_index = isci_remote_device->index;
+
+ if (isci_controller->remote_device[device_index] == NULL) {
+ /* This new device is now ready, so put it in the controller's
+ * remote device list so it is visible to CAM.
+ */
+ isci_controller->remote_device[device_index] =
+ isci_remote_device;
+
+ if (isci_controller->sim != NULL) {
+ /* The sim object is not NULL, meaning we have attached
+ * the controller to CAM already. In that case, create
+ * a CCB to instruct CAM to rescan this device.
+ * If the sim object is NULL, this device will get
+ * scanned as part of the initial scan when the
+ * controller is attached to CAM.
+ */
+ union ccb *ccb = xpt_alloc_ccb_nowait();
+
+ xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+ cam_sim_path(isci_controller->sim),
+ isci_remote_device->index, CAM_LUN_WILDCARD);
+
+ xpt_rescan(ccb);
+ }
+ }
+
+ isci_remote_device_release_device_queue(isci_remote_device);
+}
+
+/**
+ * @brief This callback method informs the framework user that the remote
+ * device is not ready. Thus, it is incapable of processing IO
+ * requests.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] remote_device This parameter specifies the device object with
+ * which this callback is associated.
+ *
+ * @return none
+ */
+void
+scif_cb_remote_device_not_ready(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device)
+{
+
+}
+
+/**
+ * @brief This callback method informs the framework user that the remote
+ * device failed. This typically occurs shortly after the device
+ * has been discovered, during the configuration phase for the device.
+ *
+ * @param[in] controller This parameter specifies the controller object
+ * with which this callback is associated.
+ * @param[in] domain This parameter specifies the domain object with
+ * which this callback is associated.
+ * @param[in] remote_device This parameter specifies the device object with
+ * which this callback is associated.
+ * @param[in] status This parameter specifies the specific failure condition
+ * associated with this device failure.
+ *
+ * @return none
+ */
+void
+scif_cb_remote_device_failed(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_DOMAIN_HANDLE_T domain, SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+ SCI_STATUS status)
+{
+
+}
+
+void
+isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device,
+ union ccb *ccb)
+{
+ struct ISCI_CONTROLLER *controller = remote_device->domain->controller;
+ struct ISCI_REQUEST *request;
+ struct ISCI_TASK_REQUEST *task_request;
+ SCI_STATUS status;
+
+ if (remote_device->is_resetting == TRUE) {
+ /* device is already being reset, so return immediately */
+ return;
+ }
+
+ if (sci_pool_empty(controller->request_pool)) {
+ /* No requests are available in our request pool. If this reset is tied
+ * to a CCB, ask CAM to requeue it. Otherwise, we need to put it on our
+ * pending device reset list, so that the reset will occur when a request
+ * frees up.
+ */
+ if (ccb == NULL)
+ sci_fast_list_insert_tail(
+ &controller->pending_device_reset_list,
+ &remote_device->pending_device_reset_element);
+ else {
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQUEUE_REQ;
+ xpt_done(ccb);
+ }
+ return;
+ }
+
+ isci_log_message(0, "ISCI",
+ "Sending reset to device on controller %d domain %d CAM index %d\n",
+ controller->index, remote_device->domain->index,
+ remote_device->index
+ );
+
+ sci_pool_get(controller->request_pool, request);
+ task_request = (struct ISCI_TASK_REQUEST *)request;
+
+ task_request->parent.remote_device_handle = remote_device->sci_object;
+ task_request->ccb = ccb;
+
+ remote_device->is_resetting = TRUE;
+
+ status = (SCI_STATUS) scif_task_request_construct(
+ controller->scif_controller_handle, remote_device->sci_object,
+ SCI_CONTROLLER_INVALID_IO_TAG, (void *)task_request,
+ (void *)((char*)task_request + sizeof(struct ISCI_TASK_REQUEST)),
+ &task_request->sci_object);
+
+ if (status != SCI_SUCCESS) {
+ isci_task_request_complete(controller->scif_controller_handle,
+ remote_device->sci_object, task_request->sci_object,
+ status);
+ return;
+ }
+
+ status = (SCI_STATUS)scif_controller_start_task(
+ controller->scif_controller_handle, remote_device->sci_object,
+ task_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);
+
+ if (status != SCI_SUCCESS) {
+ isci_task_request_complete(
+ controller->scif_controller_handle,
+ remote_device->sci_object, task_request->sci_object,
+ status);
+ return;
+ }
+}
+
+uint32_t
+isci_remote_device_get_bitrate(struct ISCI_REMOTE_DEVICE *remote_device)
+{
+ struct ISCI_DOMAIN *domain = remote_device->domain;
+ struct ISCI_CONTROLLER *controller = domain->controller;
+ SCI_PORT_HANDLE_T port_handle;
+ SCIC_PORT_PROPERTIES_T port_properties;
+ uint8_t phy_index;
+ SCI_PHY_HANDLE_T phy_handle;
+ SCIC_PHY_PROPERTIES_T phy_properties;
+
+ /* get a handle to the port associated with this remote device's
+ * domain
+ */
+ port_handle = scif_domain_get_scic_port_handle(domain->sci_object);
+ scic_port_get_properties(port_handle, &port_properties);
+
+ /* get the lowest numbered phy in the port */
+ phy_index = 0;
+ while ((port_properties.phy_mask != 0) &&
+ !(port_properties.phy_mask & 0x1)) {
+
+ phy_index++;
+ port_properties.phy_mask >>= 1;
+ }
+
+ /* get the properties for the lowest numbered phy */
+ scic_controller_get_phy_handle(
+ scif_controller_get_scic_handle(controller->scif_controller_handle),
+ phy_index, &phy_handle);
+ scic_phy_get_properties(phy_handle, &phy_properties);
+
+ switch (phy_properties.negotiated_link_rate) {
+ case SCI_SAS_150_GB:
+ return (150000);
+ case SCI_SAS_300_GB:
+ return (300000);
+ case SCI_SAS_600_GB:
+ return (600000);
+ default:
+ return (0);
+ }
+}
+
+void
+isci_remote_device_freeze_lun_queue(struct ISCI_REMOTE_DEVICE *remote_device,
+ lun_id_t lun)
+{
+ if (!(remote_device->frozen_lun_mask & (1 << lun))) {
+ struct cam_path *path;
+
+ xpt_create_path(&path, xpt_periph,
+ cam_sim_path(remote_device->domain->controller->sim),
+ remote_device->index, lun);
+ xpt_freeze_devq(path, 1);
+ xpt_free_path(path);
+ remote_device->frozen_lun_mask |= (1 << lun);
+ }
+}
+
+void
+isci_remote_device_release_lun_queue(struct ISCI_REMOTE_DEVICE *remote_device,
+ lun_id_t lun)
+{
+ if (remote_device->frozen_lun_mask & (1 << lun)) {
+ struct cam_path *path;
+
+ xpt_create_path(&path, xpt_periph,
+ cam_sim_path(remote_device->domain->controller->sim),
+ remote_device->index, lun);
+ xpt_release_devq(path, 1, TRUE);
+ xpt_free_path(path);
+ remote_device->frozen_lun_mask &= ~(1 << lun);
+ }
+}
+
+void
+isci_remote_device_release_device_queue(
+ struct ISCI_REMOTE_DEVICE *remote_device)
+{
+ lun_id_t lun;
+ for (lun = 0; lun < ISCI_MAX_LUN; lun++)
+ isci_remote_device_release_lun_queue(remote_device, lun);
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_sysctl.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_sysctl.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,229 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <sys/sysctl.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scic_phy.h>
+
+static int
+isci_sysctl_coalesce_timeout(SYSCTL_HANDLER_ARGS)
+{
+ struct isci_softc *isci = (struct isci_softc *)arg1;
+ int error = sysctl_handle_int(oidp, &isci->coalesce_timeout, 0, req);
+ int i;
+
+ if (error)
+ return (error);
+
+ for (i = 0; i < isci->controller_count; i++)
+ scif_controller_set_interrupt_coalescence(
+ isci->controllers[i].scif_controller_handle,
+ isci->coalesce_number, isci->coalesce_timeout);
+
+ return (0);
+}
+
+static int
+isci_sysctl_coalesce_number(SYSCTL_HANDLER_ARGS)
+{
+ struct isci_softc *isci = (struct isci_softc *)arg1;
+ int error = sysctl_handle_int(oidp, &isci->coalesce_number, 0, req);
+ int i;
+
+ if (error)
+ return (error);
+
+ for (i = 0; i < isci->controller_count; i++)
+ scif_controller_set_interrupt_coalescence(
+ isci->controllers[i].scif_controller_handle,
+ isci->coalesce_number, isci->coalesce_timeout);
+
+ return (0);
+}
+
+static void
+isci_sysctl_reset_remote_devices(struct ISCI_CONTROLLER *controller,
+ uint32_t remote_devices_to_be_reset)
+{
+ uint32_t i = 0;
+
+ while (remote_devices_to_be_reset != 0) {
+ if (remote_devices_to_be_reset & 0x1) {
+ struct ISCI_REMOTE_DEVICE *remote_device =
+ controller->remote_device[i];
+
+ if (remote_device != NULL) {
+ mtx_lock(&controller->lock);
+ isci_remote_device_reset(remote_device, NULL);
+ mtx_unlock(&controller->lock);
+ }
+ }
+ remote_devices_to_be_reset >>= 1;
+ i++;
+ }
+}
+
+static int
+isci_sysctl_reset_remote_device_on_controller0(SYSCTL_HANDLER_ARGS)
+{
+ struct isci_softc *isci = (struct isci_softc *)arg1;
+ uint32_t remote_devices_to_be_reset = 0;
+ struct ISCI_CONTROLLER *controller = &isci->controllers[0];
+ int error = sysctl_handle_int(oidp, &remote_devices_to_be_reset, 0, req);
+
+ if (error || remote_devices_to_be_reset == 0)
+ return (error);
+
+ isci_sysctl_reset_remote_devices(controller, remote_devices_to_be_reset);
+
+ return (0);
+}
+
+static int
+isci_sysctl_reset_remote_device_on_controller1(SYSCTL_HANDLER_ARGS)
+{
+ struct isci_softc *isci = (struct isci_softc *)arg1;
+ uint32_t remote_devices_to_be_reset = 0;
+ struct ISCI_CONTROLLER *controller = &isci->controllers[1];
+ int error =
+ sysctl_handle_int(oidp, &remote_devices_to_be_reset, 0, req);
+
+ if (error || remote_devices_to_be_reset == 0)
+ return (error);
+
+ isci_sysctl_reset_remote_devices(controller,
+ remote_devices_to_be_reset);
+
+ return (0);
+}
+
+static void
+isci_sysctl_stop(struct ISCI_CONTROLLER *controller, uint32_t phy_to_be_stopped)
+{
+ SCI_PHY_HANDLE_T phy_handle = NULL;
+
+ scic_controller_get_phy_handle(
+ scif_controller_get_scic_handle(controller->scif_controller_handle),
+ phy_to_be_stopped, &phy_handle);
+
+ scic_phy_stop(phy_handle);
+}
+
+static int
+isci_sysctl_stop_phy(SYSCTL_HANDLER_ARGS)
+{
+ struct isci_softc *isci = (struct isci_softc *)arg1;
+ uint32_t phy_to_be_stopped = 0xff;
+ uint32_t controller_index, phy_index;
+ int error = sysctl_handle_int(oidp, &phy_to_be_stopped, 0, req);
+
+ controller_index = phy_to_be_stopped / SCI_MAX_PHYS;
+ phy_index = phy_to_be_stopped % SCI_MAX_PHYS;
+
+ if(error || controller_index >= isci->controller_count)
+ return (error);
+
+ isci_sysctl_stop(&isci->controllers[controller_index], phy_index);
+
+ return (0);
+}
+
+static void
+isci_sysctl_start(struct ISCI_CONTROLLER *controller,
+ uint32_t phy_to_be_started)
+{
+ SCI_PHY_HANDLE_T phy_handle = NULL;
+
+ scic_controller_get_phy_handle(
+ scif_controller_get_scic_handle(controller->scif_controller_handle),
+ phy_to_be_started, &phy_handle);
+
+ scic_phy_start(phy_handle);
+}
+
+static int
+isci_sysctl_start_phy(SYSCTL_HANDLER_ARGS)
+{
+ struct isci_softc *isci = (struct isci_softc *)arg1;
+ uint32_t phy_to_be_started = 0xff;
+ uint32_t controller_index, phy_index;
+ int error = sysctl_handle_int(oidp, &phy_to_be_started, 0, req);
+
+ controller_index = phy_to_be_started / SCI_MAX_PHYS;
+ phy_index = phy_to_be_started % SCI_MAX_PHYS;
+
+ if(error || controller_index >= isci->controller_count)
+ return error;
+
+ isci_sysctl_start(&isci->controllers[controller_index], phy_index);
+
+ return 0;
+}
+
+void isci_sysctl_initialize(struct isci_softc *isci)
+{
+ struct sysctl_ctx_list *sysctl_ctx = device_get_sysctl_ctx(isci->device);
+ struct sysctl_oid *sysctl_tree = device_get_sysctl_tree(isci->device);
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "coalesce_timeout", CTLTYPE_UINT | CTLFLAG_RW, isci, 0,
+ isci_sysctl_coalesce_timeout, "IU",
+ "Interrupt coalescing timeout (in microseconds)");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "coalesce_number", CTLTYPE_UINT | CTLFLAG_RW, isci, 0,
+ isci_sysctl_coalesce_number, "IU",
+ "Interrupt coalescing number");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "reset_remote_device_on_controller0", CTLTYPE_UINT| CTLFLAG_RW,
+ isci, 0, isci_sysctl_reset_remote_device_on_controller0, "IU",
+ "Reset remote device on controller 0");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "reset_remote_device_on_controller1", CTLTYPE_UINT| CTLFLAG_RW,
+ isci, 0, isci_sysctl_reset_remote_device_on_controller1, "IU",
+ "Reset remote device on controller 1");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "stop_phy", CTLTYPE_UINT| CTLFLAG_RW, isci, 0, isci_sysctl_stop_phy,
+ "IU", "Stop PHY on a controller");
+
+ SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO,
+ "start_phy", CTLTYPE_UINT| CTLFLAG_RW, isci, 0,
+ isci_sysctl_start_phy, "IU", "Start PHY on a controller");
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_task_request.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_task_request.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,258 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/isci/scil/scif_controller.h>
+#include <dev/isci/scil/scif_user_callback.h>
+
+/**
+ * @brief This user callback will inform the user that a task management
+ * request completed.
+ *
+ * @param[in] controller This parameter specifies the controller on
+ * which the task management request is completing.
+ * @param[in] remote_device This parameter specifies the remote device on
+ * which this task management request is completing.
+ * @param[in] task_request This parameter specifies the task management
+ * request that has completed.
+ * @param[in] completion_status This parameter specifies the results of
+ * the IO request operation. SCI_TASK_SUCCESS indicates
+ * successful completion.
+ *
+ * @return none
+ */
+void
+scif_cb_task_request_complete(SCI_CONTROLLER_HANDLE_T controller,
+ SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+ SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status)
+{
+
+ scif_controller_complete_task(controller, remote_device, task_request);
+ isci_task_request_complete(controller, remote_device, task_request,
+ completion_status);
+}
+
+/**
+ * @brief This method returns the Logical Unit to be utilized for this
+ * task management request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ * by the protocol standard (e.g. T10 SAS specification). Please
+ * refer to the transport task information unit description
+ * in the associated standard.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ * task request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the LUN associated with this request.
+ * @todo This should be U64?
+ */
+uint32_t
+scif_cb_task_request_get_lun(void * scif_user_task_request)
+{
+
+ /* Currently we are only doing hard resets, not LUN resets. So
+ * always returning 0 is OK here, since LUN doesn't matter for
+ * a hard device reset.
+ */
+ return (0);
+}
+
+/**
+ * @brief This method returns the task management function to be utilized
+ * for this task request.
+ *
+ * @note The contents of the value returned from this callback are defined
+ * by the protocol standard (e.g. T10 SAS specification). Please
+ * refer to the transport task information unit description
+ * in the associated standard.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ * task request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns an unsigned byte representing the task
+ * management function to be performed.
+ */
+uint8_t scif_cb_task_request_get_function(void * scif_user_task_request)
+{
+ /* SCIL supports many types of task management functions, but this
+ * driver only uses HARD_RESET.
+ */
+ return (SCI_SAS_HARD_RESET);
+}
+
+/**
+ * @brief This method returns the task management IO tag to be managed.
+ * Depending upon the task management function the value returned
+ * from this method may be ignored.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ * task request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns an unsigned 16-bit word depicting the IO
+ * tag to be managed.
+ */
+uint16_t
+scif_cb_task_request_get_io_tag_to_manage(void * scif_user_task_request)
+{
+
+ return (0);
+}
+
+/**
+ * @brief This callback method asks the user to provide the virtual
+ * address of the response data buffer for the supplied IO request.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ * task request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the virtual address for the response data buffer
+ * associated with this IO request.
+ */
+void *
+scif_cb_task_request_get_response_data_address(void * scif_user_task_request)
+{
+ struct ISCI_TASK_REQUEST *task_request =
+ (struct ISCI_TASK_REQUEST *)scif_user_task_request;
+
+ return (&task_request->sense_data);
+}
+
+/**
+ * @brief This callback method asks the user to provide the length of the
+ * response data buffer for the supplied IO request.
+ *
+ * @param[in] scif_user_task_request This parameter points to the user's
+ * task request object. It is a cookie that allows the user to
+ * provide the necessary information for this callback.
+ *
+ * @return This method returns the length of the response buffer data
+ * associated with this IO request.
+ */
+uint32_t
+scif_cb_task_request_get_response_data_length(void * scif_user_task_request)
+{
+
+ return (sizeof(struct scsi_sense_data));
+}
+
+void
+isci_task_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
+ SCI_REMOTE_DEVICE_HANDLE_T remote_device,
+ SCI_TASK_REQUEST_HANDLE_T task_request, SCI_TASK_STATUS completion_status)
+{
+ struct ISCI_TASK_REQUEST *isci_task_request =
+ (struct ISCI_TASK_REQUEST *)sci_object_get_association(task_request);
+ struct ISCI_CONTROLLER *isci_controller =
+ (struct ISCI_CONTROLLER *)sci_object_get_association(scif_controller);
+ struct ISCI_REMOTE_DEVICE *isci_remote_device =
+ (struct ISCI_REMOTE_DEVICE *)sci_object_get_association(remote_device);
+ struct ISCI_REMOTE_DEVICE *pending_remote_device;
+ BOOL retry_task = FALSE;
+ union ccb *ccb = isci_task_request->ccb;
+
+ isci_remote_device->is_resetting = FALSE;
+
+ switch (completion_status) {
+ case SCI_TASK_SUCCESS:
+ case SCI_TASK_FAILURE_RESPONSE_VALID:
+ break;
+
+ case SCI_TASK_FAILURE_INVALID_STATE:
+ case SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES:
+ case SCI_FAILURE_TIMEOUT:
+ retry_task = TRUE;
+ isci_log_message(0, "ISCI",
+ "unhandled task completion code 0x%x\n", completion_status);
+ break;
+
+ case SCI_TASK_FAILURE:
+ case SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL:
+ case SCI_TASK_FAILURE_INVALID_TAG:
+ case SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR:
+ case SCI_TASK_FAILURE_TERMINATED:
+ case SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE:
+ isci_log_message(0, "ISCI",
+ "unhandled task completion code 0x%x\n", completion_status);
+ break;
+
+ default:
+ isci_log_message(0, "ISCI",
+ "unhandled task completion code 0x%x\n", completion_status);
+ break;
+ }
+
+ if (isci_controller->is_frozen == TRUE) {
+ isci_controller->is_frozen = FALSE;
+ xpt_release_simq(isci_controller->sim, TRUE);
+ }
+
+ sci_pool_put(isci_controller->request_pool,
+ (struct ISCI_REQUEST *)isci_task_request);
+
+ /* Make sure we release the device queue, since it may have been frozen
+ * if someone tried to start an I/O while the task was in progress.
+ */
+ isci_remote_device_release_device_queue(isci_remote_device);
+
+ if (retry_task == TRUE)
+ isci_remote_device_reset(isci_remote_device, ccb);
+ else {
+ pending_remote_device = sci_fast_list_remove_head(
+ &isci_controller->pending_device_reset_list);
+
+ if (pending_remote_device != NULL) {
+ /* Any resets that were triggered from an XPT_RESET_DEV
+ * CCB are never put in the pending list if the request
+ * pool is empty - they are given back to CAM to be
+ * requeued. So we will alawys pass NULL here,
+ * denoting that there is no CCB associated with the
+ * device reset.
+ */
+ isci_remote_device_reset(pending_remote_device, NULL);
+ } else if (ccb != NULL) {
+ /* There was a CCB associated with this reset, so mark
+ * it complete and return it to CAM.
+ */
+ ccb->ccb_h.status &= ~CAM_STATUS_MASK;
+ ccb->ccb_h.status |= CAM_REQ_CMP;
+ xpt_done(ccb);
+ }
+ }
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/isci_timer.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/isci_timer.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,166 @@
+/*-
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dev/isci/isci.h>
+
+#include <dev/isci/scil/scif_user_callback.h>
+
+static void
+isci_timer_timeout(void *arg)
+{
+ struct ISCI_TIMER *timer = (struct ISCI_TIMER *)arg;
+
+ isci_log_message(3, "TIMER", "timeout %p\n", timer);
+
+ /* callout_stop() will *not* keep the timer from running if it is
+ * pending. callout_drain() cannot be called from interrupt context,
+ * because it may cause thread to sleep which is not allowed in
+ * interrupt context. So instead, check the is_started flag to see if
+ * the timer routine should actually be run or not.
+ */
+ if (timer->is_started == TRUE)
+ timer->callback(timer->cookie);
+}
+
+/**
+ * @brief This callback method asks the user to start the supplied timer.
+ *
+ * @warning All timers in the system started by the SCI Framework are one
+ * shot timers. Therefore, the SCI user should make sure that it
+ * removes the timer from it's list when a timer actually fires.
+ * Additionally, SCI Framework user's should be able to handle
+ * calls from the SCI Framework to stop a timer that may already
+ * be stopped.
+ *
+ * @param[in] controller This parameter specifies the controller with
+ * which this timer is to associated.
+ * @param[in] timer This parameter specifies the timer to be started.
+ * @param[in] milliseconds This parameter specifies the number of
+ * milliseconds for which to stall. The operating system driver
+ * is allowed to round this value up where necessary.
+ *
+ * @return none
+ */
+void
+scif_cb_timer_start(SCI_CONTROLLER_HANDLE_T controller, void *timer,
+ uint32_t milliseconds)
+{
+ struct ISCI_TIMER *isci_timer = (struct ISCI_TIMER *)timer;
+
+ isci_timer->is_started = TRUE;
+ isci_log_message(3, "TIMER", "start %p %d\n", timer, milliseconds);
+ callout_reset(&isci_timer->callout, (milliseconds * hz)/1000,
+ isci_timer_timeout, timer);
+}
+
+/**
+ * @brief This callback method asks the user to stop the supplied timer.
+ *
+ * @param[in] controller This parameter specifies the controller with
+ * which this timer is to associated.
+ * @param[in] timer This parameter specifies the timer to be stopped.
+ *
+ * @return none
+ */
+void
+scif_cb_timer_stop(SCI_CONTROLLER_HANDLE_T controller, void *timer)
+{
+ struct ISCI_TIMER *isci_timer = (struct ISCI_TIMER *)timer;
+
+ isci_log_message(3, "TIMER", "stop %p\n", timer);
+ isci_timer->is_started = FALSE;
+ callout_stop(&isci_timer->callout);
+}
+
+/**
+ * @brief This callback method asks the user to create a timer and provide
+ * a handle for this timer for use in further timer interactions.
+ *
+ * @warning The "timer_callback" method should be executed in a mutually
+ * exlusive manner from the controller completion handler
+ * handler (refer to scic_controller_get_handler_methods()).
+ *
+ * @param[in] timer_callback This parameter specifies the callback method
+ * to be invoked whenever the timer expires.
+ * @param[in] controller This parameter specifies the controller with
+ * which this timer is to be associated.
+ * @param[in] cookie This parameter specifies a piece of information that
+ * the user must retain. This cookie is to be supplied by the
+ * user anytime a timeout occurs for the created timer.
+ *
+ * @return This method returns a handle to a timer object created by the
+ * user. The handle will be utilized for all further interactions
+ * relating to this timer.
+ */
+void *
+scif_cb_timer_create(SCI_CONTROLLER_HANDLE_T scif_controller,
+ SCI_TIMER_CALLBACK_T timer_callback, void *cookie)
+{
+ struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+ sci_object_get_association(scif_controller);
+ struct ISCI_TIMER *timer;
+
+ sci_pool_get(isci_controller->timer_pool, timer);
+
+ callout_init_mtx(&timer->callout, &isci_controller->lock, FALSE);
+
+ timer->callback = timer_callback;
+ timer->cookie = cookie;
+ timer->is_started = FALSE;
+
+ isci_log_message(3, "TIMER", "create %p %p %p\n", timer, timer_callback, cookie);
+
+ return (timer);
+}
+
+/**
+ * @brief This callback method asks the user to destory the supplied timer.
+ *
+ * @param[in] controller This parameter specifies the controller with
+ * which this timer is to associated.
+ * @param[in] timer This parameter specifies the timer to be destroyed.
+ *
+ * @return none
+ */
+void
+scif_cb_timer_destroy(SCI_CONTROLLER_HANDLE_T scif_controller,
+ void *timer_handle)
+{
+ struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
+ sci_object_get_association(scif_controller);
+
+ scif_cb_timer_stop(scif_controller, timer_handle);
+ sci_pool_put(isci_controller->timer_pool, (struct ISCI_TIMER *)timer_handle);
+
+ isci_log_message(3, "TIMER", "destroy %p\n", timer_handle);
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/sci_environment.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/sci_environment.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,1 @@
+/* empty file for now. compiler needs it */
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_ata.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_ata.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,654 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file defines all of the ATA related constants, enumerations,
+ * and types. Please note that this file does not necessarily contain
+ * an exhaustive list of all constants, commands, sub-commands, etc.
+ */
+
+#ifndef _ATA_H_
+#define _ATA_H_
+
+#include <dev/isci/types.h>
+
+/**
+ * @name ATA_COMMAND_CODES
+ *
+ * These constants depict the various ATA command codes defined
+ * in the ATA/ATAPI specification.
+ */
+/*@{*/
+#define ATA_IDENTIFY_DEVICE 0xEC
+#define ATA_CHECK_POWER_MODE 0xE5
+#define ATA_STANDBY 0xE2
+#define ATA_STANDBY_IMMED 0xE0
+#define ATA_IDLE_IMMED 0xE1
+#define ATA_IDLE 0xE3
+#define ATA_FLUSH_CACHE 0xE7
+#define ATA_FLUSH_CACHE_EXT 0xEA
+#define ATA_READ_DMA_EXT 0x25
+#define ATA_READ_DMA 0xC8
+#define ATA_READ_SECTORS_EXT 0x24
+#define ATA_READ_SECTORS 0x20
+#define ATA_WRITE_DMA_EXT 0x35
+#define ATA_WRITE_DMA 0xCA
+#define ATA_WRITE_SECTORS_EXT 0x34
+#define ATA_WRITE_SECTORS 0x30
+#define ATA_WRITE_UNCORRECTABLE 0x45
+#define ATA_READ_VERIFY_SECTORS 0x40
+#define ATA_READ_VERIFY_SECTORS_EXT 0x42
+#define ATA_READ_BUFFER 0xE4
+#define ATA_WRITE_BUFFER 0xE8
+#define ATA_EXECUTE_DEVICE_DIAG 0x90
+#define ATA_SET_FEATURES 0xEF
+#define ATA_SMART 0xB0
+#define ATA_PACKET_IDENTIFY 0xA1
+#define ATA_PACKET 0xA0
+#define ATA_READ_FPDMA 0x60
+#define ATA_WRITE_FPDMA 0x61
+#define ATA_READ_LOG_EXT 0x2F
+#define ATA_NOP 0x00
+#define ATA_DEVICE_RESET 0x08
+#define ATA_MEDIA_EJECT 0xED
+#define ATA_SECURITY_UNLOCK 0xF2
+#define ATA_SECURITY_FREEZE_LOCK 0xF5
+#define ATA_DATA_SET_MANAGEMENT 0x06
+#define ATA_DOWNLOAD_MICROCODE 0x92
+#define ATA_WRITE_STREAM_DMA_EXT 0x3A
+#define ATA_READ_LOG_DMA_EXT 0x47
+#define ATA_READ_STREAM_DMA_EXT 0x2A
+#define ATA_WRITE_DMA_FUA 0x3D
+#define ATA_WRITE_LOG_DMA_EXT 0x57
+#define ATA_READ_DMA_QUEUED 0xC7
+#define ATA_READ_DMA_QUEUED_EXT 0x26
+#define ATA_WRITE_DMA_QUEUED 0xCC
+#define ATA_WRITE_DMA_QUEUED_EXT 0x36
+#define ATA_WRITE_DMA_QUEUED_FUA_EXT 0x3E
+#define ATA_READ_MULTIPLE 0xC4
+#define ATA_READ_MULTIPLE_EXT 0x29
+#define ATA_WRITE_MULTIPLE 0xC5
+#define ATA_WRITE_MULTIPLE_EXT 0x39
+#define ATA_WRITE_MULTIPLE_FUA_EXT 0xCE
+
+
+/*@}*/
+
+/**
+ * @name ATA_SMART_SUB_COMMAND_CODES
+ *
+ * These constants define the ATA SMART command sub-codes that can be
+ * executed.
+ */
+/*@{*/
+#define ATA_SMART_SUB_CMD_ENABLE 0xD8
+#define ATA_SMART_SUB_CMD_DISABLE 0xD9
+#define ATA_SMART_SUB_CMD_RETURN_STATUS 0xDA
+#define ATA_SMART_SUB_CMD_READ_LOG 0xD5
+/*@}*/
+
+/**
+ * @name ATA_SET_FEATURES_SUB_COMMAND_CODES
+ *
+ * These constants define the ATA SET FEATURES command sub-codes that can
+ * be executed.
+ */
+/*@{*/
+#define ATA_SET_FEATURES_SUB_CMD_ENABLE_CACHE 0x02
+#define ATA_SET_FEATURES_SUB_CMD_DISABLE_CACHE 0x82
+#define ATA_SET_FEATURES_SUB_CMD_DISABLE_READ_AHEAD 0x55
+#define ATA_SET_FEATURES_SUB_CMD_ENABLE_READ_AHEAD 0xAA
+#define ATA_SET_FEATURES_SUB_CMD_SET_TRANSFER_MODE 0x3
+/*@}*/
+
+/**
+ * @name ATA_READ_LOG_EXT_PAGE_CODES
+ *
+ * This is a list of log page codes available for use.
+ */
+/*@{*/
+#define ATA_LOG_PAGE_NCQ_ERROR 0x10
+#define ATA_LOG_PAGE_SMART_SELF_TEST 0x06
+#define ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST 0x07
+/*@}*/
+
+/**
+ * @name ATA_LOG_PAGE_NCQ_ERROR_CONSTANTS
+ *
+ * These constants define standard values for use when requesting the NCQ
+ * error log page.
+ */
+/*@{*/
+#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR 0
+#define ATA_LOG_PAGE_NCQ_ERROR_SECTOR_COUNT 1
+/*@}*/
+
+/**
+ * @name ATA_STATUS_REGISTER_BITS
+ *
+ * The following are status register bit definitions per ATA/ATAPI-7.
+ */
+/*@{*/
+#define ATA_STATUS_REG_BSY_BIT 0x80
+#define ATA_STATUS_REG_DEVICE_FAULT_BIT 0x20
+#define ATA_STATUS_REG_ERROR_BIT 0x01
+/*@}*/
+
+/**
+ * @name ATA_ERROR_REGISTER_BITS
+ *
+ * The following are error register bit definitions per ATA/ATAPI-7.
+ */
+/*@{*/
+#define ATA_ERROR_REG_NO_MEDIA_BIT 0x02
+#define ATA_ERROR_REG_ABORT_BIT 0x04
+#define ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT 0x08
+#define ATA_ERROR_REG_ID_NOT_FOUND_BIT 0x10
+#define ATA_ERROR_REG_MEDIA_CHANGE_BIT 0x20
+#define ATA_ERROR_REG_UNCORRECTABLE_BIT 0x40
+#define ATA_ERROR_REG_WRITE_PROTECTED_BIT 0x40
+#define ATA_ERROR_REG_ICRC_BIT 0x80
+/*@}*/
+
+/**
+ * @name ATA_CONTROL_REGISTER_BITS
+ *
+ * The following are control register bit definitions per ATA/ATAPI-7
+ */
+/*@{*/
+#define ATA_CONTROL_REG_INTERRUPT_ENABLE_BIT 0x02
+#define ATA_CONTROL_REG_SOFT_RESET_BIT 0x04
+#define ATA_CONTROL_REG_HIGH_ORDER_BYTE_BIT 0x80
+/*@}*/
+
+/**
+ * @name ATA_DEVICE_HEAD_REGISTER_BITS
+ *
+ * The following are device/head register bit definitions per ATA/ATAPI-7.
+ */
+/*@{*/
+#define ATA_DEV_HEAD_REG_LBA_MODE_ENABLE 0x40
+#define ATA_DEV_HEAD_REG_FUA_ENABLE 0x80
+/*@}*/
+
+/**
+ * @name ATA_IDENTIFY_DEVICE_FIELD_LENGTHS
+ *
+ * The following constants define the number of bytes contained in various
+ * fields found in the IDENTIFY DEVICE data structure.
+ */
+/*@{*/
+#define ATA_IDENTIFY_SERIAL_NUMBER_LEN 20
+#define ATA_IDENTIFY_MODEL_NUMBER_LEN 40
+#define ATA_IDENTIFY_FW_REVISION_LEN 8
+#define ATA_IDENTIFY_48_LBA_LEN 8
+#define ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN 30
+#define ATA_IDENTIFY_WWN_LEN 8
+/*@}*/
+
+/**
+ * @name ATA_IDENTIFY_DEVICE_FIELD_MASKS
+ *
+ * The following constants define bit masks utilized to determine if a
+ * feature is supported/enabled or if a bit is simply set inside of the
+ * IDENTIFY DEVICE data structre.
+ */
+/*@{*/
+#define ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE 0x0080
+#define ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE 0x0100
+#define ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE 0x2000
+#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE 0x0001
+#define ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE 0x0400
+#define ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE 0x0100
+#define ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE 0x0001
+#define ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE 0x0100
+#define ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE 0x001F
+#define ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE 0x0100
+#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK 0x000F
+#define ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE 0x2000
+#define ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT 0x0004
+#define ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED 0x0002
+#define ATA_IDENTIFY_COMMAND_SET_DSM_TRIM_SUPPORTED 0x0001
+#define ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_DETERMINISTIC_READ 0x4000
+#define ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_READ_ZERO 0x0020
+/*@}*/
+
+/**
+ * @name ATAPI_IDENTIFY_DEVICE_FIELD_MASKS
+ *
+ * These constants define the various bit definitions for the
+ * fields in the PACKET IDENTIFY DEVICE data structure.
+ */
+/*@{*/
+#define ATAPI_IDENTIFY_16BYTE_CMD_PCKT_ENABLE 0x01
+/*@}*/
+
+/**
+ * @name ATA_PACKET_FEATURE_BITS
+ *
+ * These constants define the various bit definitions for the
+ * ATA PACKET feature register.
+ */
+/*@{*/
+#define ATA_PACKET_FEATURE_DMA 0x01
+#define ATA_PACKET_FEATURE_OVL 0x02
+#define ATA_PACKET_FEATURE_DMADIR 0x04
+/*@}*/
+
+/**
+ * @name ATA_Device_Power_Mode_Values
+ *
+ * These constants define the power mode values returned by
+ * ATA_Check_Power_Mode
+ */
+/*@{*/
+#define ATA_STANDBY_POWER_MODE 0x00
+#define ATA_IDLE_POWER_MODE 0x80
+#define ATA_ACTIVE_POWER_MODE 0xFF
+/*@}*/
+
+/**
+ * @name ATA_WRITE_UNCORRECTIABLE feature field values
+ *
+ * These constants define the Write Uncorrectable feature values
+ * used with the SATI translation.
+ */
+/*@{*/
+#define ATA_WRITE_UNCORRECTABLE_PSUEDO 0x55
+#define ATA_WRITE_UNCORRECTABLE_FLAGGED 0xAA
+/*@}*/
+
+
+
+/**
+ * @name ATA_SECURITY_STATUS field values
+ *
+ * These constants define the mask of the securityStatus field and the various bits within it
+ */
+/*@{*/
+#define ATA_SECURITY_STATUS_SUPPORTED 0x0001
+#define ATA_SECURITY_STATUS_ENABLED 0x0002
+#define ATA_SECURITY_STATUS_LOCKED 0x0004
+#define ATA_SECURITY_STATUS_FROZEN 0x0008
+#define ATA_SECURITY_STATUS_EXPIRED 0x0010
+#define ATA_SECURITY_STATUS_ERASESUPPORTED 0x0020
+#define ATA_SECURITY_STATUS_RESERVED 0xFEC0
+#define ATA_SECURITY_STATUS_SECURITYLEVEL 0x0100
+/*@}*/
+
+/**
+ * @struct ATA_IDENTIFY_DEVICE
+ *
+ * @brief This structure depicts the ATA IDENTIFY DEVICE data format.
+ */
+typedef struct ATA_IDENTIFY_DEVICE_DATA
+{
+ U16 general_config_bits; // word 00
+ U16 obsolete0; // word 01 (num cylinders)
+ U16 vendor_specific_config_bits; // word 02
+ U16 obsolete1; // word 03 (num heads)
+ U16 retired1[2]; // words 04-05
+ U16 obsolete2; // word 06 (sectors / track)
+ U16 reserved_for_compact_flash1[2]; // words 07-08
+ U16 retired0; // word 09
+ U8 serial_number[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; // word 10-19
+ U16 retired2[2]; // words 20-21
+ U16 obsolete4; // word 22
+ U8 firmware_revision[ATA_IDENTIFY_FW_REVISION_LEN]; // words 23-26
+ U8 model_number[ATA_IDENTIFY_MODEL_NUMBER_LEN]; // words 27-46
+ U16 max_sectors_per_multiple; // word 47
+ U16 reserved0; // word 48
+ U16 capabilities1; // word 49
+ U16 capabilities2; // word 50
+ U16 obsolete5[2]; // words 51-52
+ U16 validity_bits; // word 53
+ U16 obsolete6[5]; // words 54-58 Used to be:
+ // current cylinders,
+ // current heads,
+ // current sectors/Track,
+ // current capacity
+ U16 current_max_sectors_per_multiple; // word 59
+ U8 total_num_sectors[4]; // words 60-61
+ U16 obsolete7; // word 62
+ U16 multi_word_dma_mode; // word 63
+ U16 pio_modes_supported; // word 64
+ U16 min_multiword_dma_transfer_cycle; // word 65
+ U16 rec_min_multiword_dma_transfer_cycle; // word 66
+ U16 min_pio_transfer_no_flow_ctrl; // word 67
+ U16 min_pio_transfer_with_flow_ctrl; // word 68
+ U16 additional_supported; // word 69
+ U16 reserved1; // word 70
+ U16 reserved2[4]; // words 71-74
+ U16 queue_depth; // word 75
+ U16 serial_ata_capabilities; // word 76
+ U16 serial_ata_reserved; // word 77
+ U16 serial_ata_features_supported; // word 78
+ U16 serial_ata_features_enabled; // word 79
+ U16 major_version_number; // word 80
+ U16 minor_version_number; // word 81
+ U16 command_set_supported0; // word 82
+ U16 command_set_supported1; // word 83
+ U16 command_set_supported_extention; // word 84
+ U16 command_set_enabled0; // word 85
+ U16 command_set_enabled1; // word 86
+ U16 command_set_default; // word 87
+ U16 ultra_dma_mode; // word 88
+ U16 security_erase_completion_time; // word 89
+ U16 enhanced_security_erase_time; // word 90
+ U16 current_power_mgmt_value; // word 91
+ U16 master_password_revision; // word 92
+ U16 hardware_reset_result; // word 93
+ U16 current_acoustic_management_value; // word 94
+ U16 stream_min_request_size; // word 95
+ U16 stream_transfer_time; // word 96
+ U16 stream_access_latency; // word 97
+ U16 stream_performance_granularity[2]; // words 98-99
+ U8 max_48bit_lba[ATA_IDENTIFY_48_LBA_LEN]; // words 100-103
+ U16 streaming_transfer_time; // word 104
+ U16 max_lba_range_entry_blocks; // word 105
+ U16 physical_logical_sector_info; // word 106
+ U16 acoustic_test_interseek_delay; // word 107
+ U8 world_wide_name[ATA_IDENTIFY_WWN_LEN]; // words 108-111
+ U8 reserved_for_wwn_extention[ATA_IDENTIFY_WWN_LEN];// words 112-115
+ U16 reserved4; // word 116
+ U8 words_per_logical_sector[4]; // words 117-118
+ U16 command_set_supported2; // word 119
+ U16 reserved5[7]; // words 120-126
+ U16 removable_media_status; // word 127
+ U16 security_status; // word 128
+ U16 vendor_specific1[31]; // words 129-159
+ U16 cfa_power_mode1; // word 160
+ U16 reserved_for_compact_flash2[7]; // words 161-167
+ U16 device_nominal_form_factor; // word 168
+ U16 data_set_management; // word 169
+ U16 reserved_for_compact_flash3[6]; // words 170-175
+ U16 current_media_serial_number[ATA_IDENTIFY_MEDIA_SERIAL_NUMBER_LEN];//words 176-205
+ U16 reserved6[3]; // words 206-208
+ U16 logical_sector_alignment; // words 209
+ U16 reserved7[7]; // words 210-216
+ U16 nominal_media_rotation_rate; // word 217
+ U16 reserved8[16]; // words 218-233
+ U16 min_num_blocks_per_microcode; // word 234
+ U16 max_num_blocks_per_microcode; // word 235
+ U16 reserved9[19]; // words 236-254
+ U16 integrity_word; // word 255
+
+} ATA_IDENTIFY_DEVICE_DATA_T;
+
+#define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \
+ ((POINTER_UINT)&(((ATA_IDENTIFY_DEVICE_DATA_T*)0)->field_name))
+#define ATA_IDENTIFY_DEVICE_WCE_ENABLE 0x20
+#define ATA_IDENTIFY_DEVICE_RA_ENABLE 0x40
+
+/**
+ * @struct ATAPI_IDENTIFY_PACKET_DATA
+ *
+ * @brief The following structure depicts the ATA-ATAPI 7 version of the
+ * IDENTIFY PACKET DEVICE data structure.
+ */
+typedef struct ATAPI_IDENTIFY_PACKET_DEVICE
+{
+ U16 generalConfigBits; // word 00
+ U16 reserved0; // word 01 (num cylinders)
+ U16 uniqueConfigBits; // word 02
+ U16 reserved1[7]; // words 03 - 09
+ U8 serialNumber[ATA_IDENTIFY_SERIAL_NUMBER_LEN]; // word 10-19
+ U16 reserved2[3]; // words 20-22
+ U8 firmwareRevision[ATA_IDENTIFY_FW_REVISION_LEN];// words 23-26
+ U8 modelNumber[ATA_IDENTIFY_MODEL_NUMBER_LEN]; // words 27-46
+ U16 reserved4[2]; // words 47-48
+ U16 capabilities1; // word 49
+ U16 capabilities2; // word 50
+ U16 obsolete0[2]; // words 51-52
+ U16 validityBits; // word 53
+ U16 reserved[8]; // words 54-61
+
+ U16 DMADIRBitRequired; // word 62, page2
+ U16 multiWordDmaMode; // word 63
+ U16 pioModesSupported; // word 64
+ U16 minMultiwordDmaTransferCycle; // word 65
+ U16 recMinMultiwordDmaTransferCycle; // word 66
+ U16 minPioTransferNoFlowCtrl; // word 67
+ U16 minPioTransferWithFlowCtrl; // word 68
+ U16 reserved6[2]; // words 69-70
+ U16 nsFromPACKETReceiptToBusRelease; // word 71
+ U16 nsFromSERVICEReceiptToBSYreset; // wore 72
+ U16 reserved7[2]; // words 73-74
+ U16 queueDepth; // word 75
+ U16 serialAtaCapabilities; // word 76
+ U16 serialAtaReserved; // word 77
+ U16 serialAtaFeaturesSupported; // word 78
+ U16 serialAtaFeaturesEnabled; // word 79
+
+ U16 majorVersionNumber; // word 80, page3
+ U16 minorVersionNumber; // word 81
+ U16 commandSetSupported0; // word 82
+ U16 commandSetSupported1; // word 83
+
+ U16 commandSetSupportedExtention; // word 84, page4
+ U16 commandSetEnabled0; // word 85
+ U16 commandSetEnabled1; // word 86
+ U16 commandSetDefault; // word 87
+
+ U16 ultraDmaMode; // word 88, page5
+ U16 reserved8[4]; // words 89 - 92
+
+ U16 hardwareResetResult; // word 93, page6
+ U16 currentAcousticManagementValue; // word 94
+ U16 reserved9[30]; // words 95-124
+ U16 ATAPIByteCount0Behavior; // word 125
+ U16 obsolete1; // word 126
+ U16 removableMediaStatus; // word 127,
+
+ U16 securityStatus; // word 128, page7
+ U16 vendorSpecific1[31]; // words 129-159
+ U16 reservedForCompactFlash[16]; // words 160-175
+ U16 reserved10[79]; // words 176-254
+ U16 integrityWord; // word 255
+} ATAPI_IDENTIFY_PACKET_DEVICE_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+* Extended SMART self test log page descriptor entry.
+*/
+typedef union ATA_DESCRIPTOR_ENTRY
+{
+ struct DESCRIPTOR_ENTRY
+ {
+ U8 lba_field;
+ U8 status_byte;
+ U8 time_stamp_low;
+ U8 time_stamp_high;
+ U8 checkpoint_byte;
+ U8 failing_lba_low;
+ U8 failing_lba_mid;
+ U8 failing_lba_high;
+ U8 failing_lba_low_ext;
+ U8 failing_lba_mid_ext;
+ U8 failing_lba_high_ext;
+
+ U8 vendor_specific1;
+ U8 vendor_specific2;
+ U8 vendor_specific3;
+ U8 vendor_specific4;
+ U8 vendor_specific5;
+ U8 vendor_specific6;
+ U8 vendor_specific7;
+ U8 vendor_specific8;
+ U8 vendor_specific9;
+ U8 vendor_specific10;
+ U8 vendor_specific11;
+ U8 vendor_specific12;
+ U8 vendor_specific13;
+ U8 vendor_specific14;
+ U8 vendor_specific15;
+ } DESCRIPTOR_ENTRY;
+
+ U8 descriptor_entry[26];
+
+} ATA_DESCRIPTOR_ENTRY_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+* SMART self test log page descriptor entry.
+*/
+typedef union ATA_SMART_DESCRIPTOR_ENTRY
+{
+ struct SMART_DESCRIPTOR_ENTRY
+ {
+ U8 lba_field;
+ U8 status_byte;
+ U8 time_stamp_low;
+ U8 time_stamp_high;
+ U8 checkpoint_byte;
+ U8 failing_lba_low;
+ U8 failing_lba_mid;
+ U8 failing_lba_high;
+ U8 failing_lba_low_ext;
+
+ U8 vendor_specific1;
+ U8 vendor_specific2;
+ U8 vendor_specific3;
+ U8 vendor_specific4;
+ U8 vendor_specific5;
+ U8 vendor_specific6;
+ U8 vendor_specific7;
+ U8 vendor_specific8;
+ U8 vendor_specific9;
+ U8 vendor_specific10;
+ U8 vendor_specific11;
+ U8 vendor_specific12;
+ U8 vendor_specific13;
+ U8 vendor_specific14;
+ U8 vendor_specific15;
+ } SMART_DESCRIPTOR_ENTRY;
+
+ U8 smart_descriptor_entry[24];
+
+} ATA_SMART_DESCRIPTOR_ENTRY_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+* Extended SMART self test log page.
+*/
+typedef struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+{
+ U8 self_test_log_data_structure_revision_number; //byte 0
+ U8 reserved0; //byte 1
+ U8 self_test_descriptor_index[2]; //byte 2-3
+
+ ATA_DESCRIPTOR_ENTRY_T descriptor_entrys[19]; //bytes 4-497
+
+ U8 vendor_specific[2]; //byte 498-499
+ U8 reserved1[11]; //byte 500-510
+ U8 data_structure_checksum; //byte 511
+
+} ATA_EXTENDED_SMART_SELF_TEST_LOG_T;
+
+/**
+* @struct ATA_EXTENDED_SMART_SELF_TEST_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+* SMART self test log page.
+*/
+typedef struct ATA_SMART_SELF_TEST_LOG
+{
+ U8 self_test_log_data_structure_revision_number[2]; //bytes 0-1
+
+ ATA_SMART_DESCRIPTOR_ENTRY_T descriptor_entrys[21]; //bytes 2-505
+
+ U8 vendor_specific[2]; //byte 506-507
+ U8 self_test_index; //byte 508
+ U8 reserved1[2]; //byte 509-510
+ U8 data_structure_checksum; //byte 511
+
+} ATA_SMART_SELF_TEST_LOG_T;
+
+/**
+* @struct ATA_NCQ_COMMAND_ERROR_LOG
+*
+* @brief The following structure depicts the ATA-8 version of the
+* NCQ command error log page.
+*/
+typedef struct ATA_NCQ_COMMAND_ERROR_LOG
+{
+ U8 ncq_tag : 5;
+ U8 reserved1 : 2;
+ U8 nq : 1;
+ U8 reserved2;
+ U8 status;
+ U8 error;
+ U8 lba_7_0;
+ U8 lba_15_8;
+ U8 lba_23_16;
+ U8 device;
+ U8 lba_31_24;
+ U8 lba_39_32;
+ U8 lba_47_40;
+ U8 reserved3;
+ U8 count_7_0;
+ U8 count_15_8;
+ U8 reserved4[242];
+ U8 vendor_specific[255];
+ U8 checksum;
+} ATA_NCQ_COMMAND_ERROR_LOG_T;
+
+#endif // _ATA_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_pci.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_pci.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,90 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _INTEL_PCI_H_
+#define _INTEL_PCI_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the definitions relating to structures,
+ * constants, etc. defined by the PCI specification.
+ */
+
+#include <dev/isci/types.h>
+
+typedef struct sci_pci_common_header
+{
+ // Offset 0x00
+ U16 vendor_id;
+ U16 device_id;
+
+ // Offset 0x04
+ U16 command;
+ U16 status;
+
+ // Offset 0x08
+ U8 revision;
+ U8 program_interface;
+ U8 sub_class;
+ U8 base_class;
+
+ // Offset 0x0C
+ U8 cache_line_size;
+ U8 master_latency_timer;
+ U8 header_type;
+ U8 built_in_self_test;
+
+} SCI_PCI_COMMON_HEADER_T;
+
+#endif // _INTEL_PCI_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_sas.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_sas.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,977 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _INTEL_SAS_H_
+#define _INTEL_SAS_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains all of the definitions relating to structures,
+ * constants, etc. defined by the SAS specification.
+ */
+
+#include <dev/isci/types.h>
+#include <dev/isci/scil/intel_sata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @struct SCI_SAS_ADDRESS
+ * @brief This structure depicts how a SAS address is represented by SCI.
+ */
+typedef struct SCI_SAS_ADDRESS
+{
+ /**
+ * This member contains the higher 32-bits of the SAS address.
+ */
+ U32 high;
+
+ /**
+ * This member contains the lower 32-bits of the SAS address.
+ */
+ U32 low;
+
+} SCI_SAS_ADDRESS_T;
+
+/**
+ * @struct SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS
+ * @brief This structure depicts the contents of bytes 2 and 3 in the
+ * SAS IDENTIFY ADDRESS FRAME (IAF).
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification
+ * Link layer section on address frames.
+ */
+typedef struct SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS
+{
+ union
+ {
+ struct
+ {
+ U16 restricted1 : 1;
+ U16 smp_initiator : 1;
+ U16 stp_initiator : 1;
+ U16 ssp_initiator : 1;
+ U16 reserved3 : 4;
+ U16 restricted2 : 1;
+ U16 smp_target : 1;
+ U16 stp_target : 1;
+ U16 ssp_target : 1;
+ U16 reserved4 : 4;
+ } bits;
+
+ U16 all;
+ } u;
+
+} SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T;
+
+/**
+ * @struct SCI_SAS_IDENTIFY_ADDRESS_FRAME
+ * @brief This structure depicts the contents of the SAS IDENTIFY ADDRESS
+ * FRAME (IAF).
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification
+ * Link layer section on address frames.
+ */
+typedef struct SCI_SAS_IDENTIFY_ADDRESS_FRAME
+{
+ U16 address_frame_type : 4;
+ U16 device_type : 3;
+ U16 reserved1 : 1;
+ U16 reason : 4;
+ U16 reserved2 : 4;
+
+ SCI_SAS_IDENTIFY_ADDRESS_FRAME_PROTOCOLS_T protocols;
+
+ SCI_SAS_ADDRESS_T device_name;
+ SCI_SAS_ADDRESS_T sas_address;
+
+ U32 phy_identifier : 8;
+ U32 break_reply_capable : 1;
+ U32 requested_in_zpsds : 1;
+ U32 in_zpsds_persistent : 1;
+ U32 reserved5 : 21;
+
+ U32 reserved6[4];
+
+} SCI_SAS_IDENTIFY_ADDRESS_FRAME_T;
+
+/**
+ * @struct SAS_CAPABILITIES
+ * @brief This structure depicts the various SAS capabilities supported
+ * by the directly attached target device. For specific information
+ * on each of these individual fields please reference the SAS
+ * specification Phy layer section on speed negotiation windows.
+ */
+typedef struct SAS_CAPABILITIES
+{
+ union
+ {
+#if defined (SCIC_SDS_4_ENABLED)
+ struct
+ {
+ /**
+ * The SAS specification indicates the start bit shall always be set to
+ * 1. This implementation will have the start bit set to 0 if the
+ * PHY CAPABILITIES were either not received or speed negotiation failed.
+ */
+ U32 start : 1;
+ U32 tx_ssc_type : 1;
+ U32 reserved1 : 2;
+ U32 requested_logical_link_rate : 4;
+
+ U32 gen1_without_ssc_supported : 1;
+ U32 gen1_with_ssc_supported : 1;
+ U32 gen2_without_ssc_supported : 1;
+ U32 gen2_with_ssc_supported : 1;
+ U32 gen3_without_ssc_supported : 1;
+ U32 gen3_with_ssc_supported : 1;
+ U32 reserved2 : 17;
+ U32 parity : 1;
+ } bits;
+#endif // (SCIC_SDS_4_ENABLED)
+
+ U32 all;
+ } u;
+
+} SAS_CAPABILITIES_T;
+
+/**
+ * @enum _SCI_SAS_LINK_RATE
+ * @brief This enumeration depicts the SAS specification defined link speeds.
+ */
+typedef enum _SCI_SAS_LINK_RATE
+{
+ SCI_SAS_NO_LINK_RATE = 0,
+ SCI_SATA_SPINUP_HOLD = 0x3,
+ SCI_SAS_150_GB = 0x8,
+ SCI_SAS_300_GB = 0x9,
+ SCI_SAS_600_GB = 0xA
+} SCI_SAS_LINK_RATE;
+
+/**
+ * @enum _SCI_SAS_TASK_ATTRIBUTE
+ * @brief This enumeration depicts the SAM/SAS specification defined task
+ * attribute values for a command information unit.
+ */
+typedef enum _SCI_SAS_TASK_ATTRIBUTE
+{
+ SCI_SAS_SIMPLE_ATTRIBUTE = 0,
+ SCI_SAS_HEAD_OF_QUEUE_ATTRIBUTE = 1,
+ SCI_SAS_ORDERED_ATTRIBUTE = 2,
+ SCI_SAS_ACA_ATTRIBUTE = 4,
+} SCI_SAS_TASK_ATTRIBUTE;
+
+/**
+ * @enum _SCI_SAS_TASK_MGMT_FUNCTION
+ * @brief This enumeration depicts the SAM/SAS specification defined task
+ * management functions.
+ * @note This HARD_RESET function listed here is not actually defined
+ * as a task management function in the industry standard.
+ */
+typedef enum _SCI_SAS_TASK_MGMT_FUNCTION
+{
+ SCI_SAS_ABORT_TASK = SCSI_TASK_REQUEST_ABORT_TASK,
+ SCI_SAS_ABORT_TASK_SET = SCSI_TASK_REQUEST_ABORT_TASK_SET,
+ SCI_SAS_CLEAR_TASK_SET = SCSI_TASK_REQUEST_CLEAR_TASK_SET,
+ SCI_SAS_LOGICAL_UNIT_RESET = SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET,
+ SCI_SAS_I_T_NEXUS_RESET = SCSI_TASK_REQUEST_I_T_NEXUS_RESET,
+ SCI_SAS_CLEAR_ACA = SCSI_TASK_REQUEST_CLEAR_ACA,
+ SCI_SAS_QUERY_TASK = SCSI_TASK_REQUEST_QUERY_TASK,
+ SCI_SAS_QUERY_TASK_SET = SCSI_TASK_REQUEST_QUERY_TASK_SET,
+ SCI_SAS_QUERY_ASYNCHRONOUS_EVENT = SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION,
+ SCI_SAS_HARD_RESET = 0xFF
+} SCI_SAS_TASK_MGMT_FUNCTION_T;
+
+
+/**
+ * @enum _SCI_SAS_FRAME_TYPE
+ * @brief This enumeration depicts the SAS specification defined SSP frame
+ * types.
+ */
+typedef enum _SCI_SAS_FRAME_TYPE
+{
+ SCI_SAS_DATA_FRAME = 0x01,
+ SCI_SAS_XFER_RDY_FRAME = 0x05,
+ SCI_SAS_COMMAND_FRAME = 0x06,
+ SCI_SAS_RESPONSE_FRAME = 0x07,
+ SCI_SAS_TASK_FRAME = 0x16
+} SCI_SAS_FRAME_TYPE_T;
+
+
+/**
+ * @struct SCI_SSP_COMMAND_IU
+ * @brief This structure depicts the contents of the SSP COMMAND
+ * INFORMATION UNIT. For specific information on each of these
+ * individual fields please reference the SAS specification SSP
+ * transport layer section.
+ */
+typedef struct SCI_SSP_COMMAND_IU
+{
+
+ U32 lun[2];
+
+ U32 additional_cdb_length : 6;
+ U32 reserved0 : 2;
+ U32 reserved1 : 8;
+ U32 enable_first_burst : 1;
+ U32 task_priority : 4;
+ U32 task_attribute : 3;
+ U32 reserved2 : 8;
+
+ U32 cdb[4];
+
+} SCI_SSP_COMMAND_IU_T;
+
+/**
+ * @struct SCI_SSP_TASK_IU
+ * @brief This structure depicts the contents of the SSP TASK INFORMATION
+ * UNIT. For specific information on each of these individual fields
+ * please reference the SAS specification SSP transport layer
+ * section.
+ */
+typedef struct SCI_SSP_TASK_IU
+{
+ U32 lun_upper;
+ U32 lun_lower;
+
+ U32 reserved0 : 8;
+ U32 task_function : 8;
+ U32 reserved1 : 8;
+ U32 reserved2 : 8;
+
+ U32 reserved3 : 16;
+ U32 task_tag : 16;
+
+ U32 reserved4[3];
+
+} SCI_SSP_TASK_IU_T;
+
+#define SSP_RESPONSE_IU_MAX_DATA 64
+
+#define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK (0x03)
+
+/**
+ * @struct SCI_SSP_RESPONSE_IU
+ * @brief This structure depicts the contents of the SSP RESPONSE
+ * INFORMATION UNIT. For specific information on each of these
+ * individual fields please reference the SAS specification SSP
+ * transport layer section.
+ */
+typedef struct SCI_SSP_RESPONSE_IU
+{
+ U8 reserved0[8];
+
+ U8 retry_delay_timer[2];
+ U8 data_present;
+ U8 status;
+
+ U8 reserved1[4];
+ U8 sense_data_length[4];
+ U8 response_data_length[4];
+
+ U32 data[SSP_RESPONSE_IU_MAX_DATA];
+
+} SCI_SSP_RESPONSE_IU_T;
+
+/**
+ * @enum _SCI_SAS_DATA_PRESENT_TYPE
+ * @brief This enumeration depicts the SAS specification defined SSP data present
+ * types in SCI_SSP_RESPONSE_IU.
+ */
+typedef enum _SCI_SSP_RESPONSE_IU_DATA_PRESENT_TYPE
+{
+ SCI_SSP_RESPONSE_IU_NO_DATA = 0x00,
+ SCI_SSP_RESPONSE_IU_RESPONSE_DATA = 0x01,
+ SCI_SSP_RESPONSE_IU_SENSE_DATA = 0x02
+} SCI_SSP_RESPONSE_IU_DATA_PRESENT_TYPE_T;
+
+/**
+ * @struct SCI_SSP_FRAME_HEADER
+ *
+ * @brief This structure depicts the contents of an SSP frame header. For
+ * specific information on the individual fields please reference
+ * the SAS specification transport layer SSP frame format.
+ */
+typedef struct SCI_SSP_FRAME_HEADER
+{
+ // Word 0
+ U32 hashed_destination_address :24;
+ U32 frame_type : 8;
+
+ // Word 1
+ U32 hashed_source_address :24;
+ U32 reserved1_0 : 8;
+
+ // Word 2
+ U32 reserved2_2 : 6;
+ U32 fill_bytes : 2;
+ U32 reserved2_1 : 3;
+ U32 tlr_control : 2;
+ U32 retry_data_frames : 1;
+ U32 retransmit : 1;
+ U32 changing_data_pointer : 1;
+ U32 reserved2_0 :16;
+
+ // Word 3
+ U32 uiResv4;
+
+ // Word 4
+ U16 target_port_transfer_tag;
+ U16 tag;
+
+ // Word 5
+ U32 data_offset;
+
+} SCI_SSP_FRAME_HEADER_T;
+
+/**
+ * @struct SMP_REQUEST_HEADER
+ * @brief This structure defines the contents of an SMP Request header.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_HEADER
+{
+ U8 smp_frame_type; // byte 0
+ U8 function; // byte 1
+ U8 allocated_response_length; // byte 2
+ U8 request_length; // byte 3
+} SMP_REQUEST_HEADER_T;
+
+/**
+ * @struct SMP_RESPONSE_HEADER
+ * @brief This structure depicts the contents of the SAS SMP DISCOVER
+ * RESPONSE frame. For specific information on each of these
+ * individual fields please reference the SAS specification Link
+ * layer section on address frames.
+ */
+typedef struct SMP_RESPONSE_HEADER
+{
+ U8 smp_frame_type; // byte 0
+ U8 function; // byte 1
+ U8 function_result; // byte 2
+ U8 response_length; // byte 3
+} SMP_RESPONSE_HEADER_T;
+
+/**
+ * @struct SMP_REQUEST_GENERAL
+ * @brief This structure defines the contents of an SMP Request that
+ * is comprised of the SMP_REQUEST_HEADER and a CRC.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_GENERAL
+{
+ U32 crc; // bytes 4-7
+
+} SMP_REQUEST_GENERAL_T;
+
+/**
+ * @struct SMP_REQUEST_PHY_IDENTIFIER
+ * @brief This structure defines the contents of an SMP Request that
+ * is comprised of the SMP_REQUEST_HEADER and a phy identifier.
+ * Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_PHY_IDENTIFIER
+{
+ U32 reserved_byte4_7; // bytes 4-7
+
+ U32 ignore_zone_group:1; // byte 8
+ U32 reserved_byte8:7;
+
+ U32 phy_identifier:8; // byte 9
+ U32 reserved_byte10:8; // byte 10
+ U32 reserved_byte11:8; // byte 11
+
+} SMP_REQUEST_PHY_IDENTIFIER_T;
+
+/**
+ * @struct SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION
+ * @brief This structure defines the contents of an SMP Configure Route
+ * Information request.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION
+{
+ U32 expected_expander_change_count:16; // bytes 4-5
+ U32 expander_route_index_high:8;
+ U32 expander_route_index:8; // bytes 6-7
+
+ U32 reserved_byte8:8; // bytes 8
+ U32 phy_identifier:8; // bytes 9
+ U32 reserved_byte_10_11:16; // bytes 10-11
+
+ U32 reserved_byte_12_bit_0_6:7;
+ U32 disable_route_entry:1; // byte 12
+ U32 reserved_byte_13_15:24; // bytes 13-15
+
+ U32 routed_sas_address[2]; // bytes 16-23
+ U8 reserved_byte_24_39[16]; // bytes 24-39
+
+} SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T;
+
+/**
+ * @struct SMP_REQUEST_PHY_CONTROL
+ * @brief This structure defines the contents of an SMP Phy Controler
+ * request.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification.
+ */
+typedef struct SMP_REQUEST_PHY_CONTROL
+{
+ U16 expected_expander_change_count; // byte 4-5
+
+ U16 reserved_byte_6_7; // byte 6-7
+ U8 reserved_byte_8; // byte 8
+
+ U8 phy_identifier; // byte 9
+ U8 phy_operation; // byte 10
+
+ U8 update_partial_pathway_timeout_value:1;
+ U8 reserved_byte_11_bit_1_7:7; // byte 11
+
+ U8 reserved_byte_12_23[12]; // byte 12-23
+
+ U8 attached_device_name[8]; // byte 24-31
+
+ U8 reserved_byte_32_bit_3_0:4; // byte 32
+ U8 programmed_minimum_physical_link_rate:4;
+
+ U8 reserved_byte_33_bit_3_0:4; // byte 33
+ U8 programmed_maximum_physical_link_rate:4;
+
+ U16 reserved_byte_34_35; // byte 34-35
+
+ U8 partial_pathway_timeout_value:4;
+ U8 reserved_byte_36_bit_4_7:4; // byte 36
+
+ U16 reserved_byte_37_38; // byte 37-38
+ U8 reserved_byte_39; // byte 39
+
+} SMP_REQUEST_PHY_CONTROL_T;
+
+/**
+ * @struct SMP_REQUEST_VENDOR_SPECIFIC
+ * @brief This structure depicts the vendor specific space for SMP request.
+ */
+ #define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016
+typedef struct SMP_REQUEST_VENDOR_SPECIFIC
+{
+ U8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
+}SMP_REQUEST_VENDOR_SPECIFIC_T;
+
+/**
+ * @struct SMP_REQUEST
+ * @brief This structure simply unionizes the existing request
+ * structures into a common request type.
+ */
+typedef struct _SMP_REQUEST
+{
+ SMP_REQUEST_HEADER_T header;
+
+ union
+ { // bytes 4-N
+ SMP_REQUEST_GENERAL_T report_general;
+ SMP_REQUEST_PHY_IDENTIFIER_T discover;
+ SMP_REQUEST_GENERAL_T report_manufacturer_information;
+ SMP_REQUEST_PHY_IDENTIFIER_T report_phy_sata;
+ SMP_REQUEST_PHY_CONTROL_T phy_control;
+ SMP_REQUEST_PHY_IDENTIFIER_T report_phy_error_log;
+ SMP_REQUEST_PHY_IDENTIFIER_T report_route_information;
+ SMP_REQUEST_CONFIGURE_ROUTE_INFORMATION_T configure_route_information;
+ SMP_REQUEST_VENDOR_SPECIFIC_T vendor_specific_request;
+ } request;
+
+} SMP_REQUEST_T;
+
+
+/**
+ * @struct SMP_RESPONSE_REPORT_GENERAL
+ * @brief This structure depicts the SMP Report General for
+ * expander devices. It adheres to the SAS-2.1 specification.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification
+ * Application layer section on SMP.
+ */
+typedef struct SMP_RESPONSE_REPORT_GENERAL
+{
+ U16 expander_change_count; //byte 4-5
+ U16 expander_route_indexes; //byte 6-7
+
+ U32 reserved_byte8:7; //byte 8 bit 0-6
+ U32 long_response:1; //byte 8 bit 7
+
+ U32 number_of_phys:8; //byte 9
+
+ U32 configurable_route_table:1; //byte 10
+ U32 configuring:1;
+ U32 configures_others:1;
+ U32 open_reject_retry_supported:1;
+ U32 stp_continue_awt:1;
+ U32 self_configuring:1;
+ U32 zone_configuring:1;
+ U32 table_to_table_supported:1;
+
+ U32 reserved_byte11:8; //byte 11
+
+ U32 enclosure_logical_identifier_high; //byte 12-15
+ U32 enclosure_logical_identifier_low; //byte 16-19
+
+ U32 reserved_byte20_23;
+ U32 reserved_byte24_27;
+
+} SMP_RESPONSE_REPORT_GENERAL_T;
+
+typedef struct SMP_RESPONSE_REPORT_GENERAL_LONG
+{
+ SMP_RESPONSE_REPORT_GENERAL_T sas1_1;
+
+ struct
+ {
+ U16 reserved1;
+ U16 stp_bus_inactivity_time_limit;
+ U16 stp_max_connect_time_limit;
+ U16 stp_smp_i_t_nexus_loss_time;
+
+ U32 zoning_enabled : 1;
+ U32 zoning_supported : 1;
+ U32 physicaL_presence_asserted : 1;
+ U32 zone_locked : 1;
+ U32 reserved2 : 1;
+ U32 num_zone_groups : 3;
+ U32 saving_zoning_enabled_supported : 3;
+ U32 saving_zone_perms_table_supported : 1;
+ U32 saving_zone_phy_info_supported : 1;
+ U32 saving_zone_manager_password_supported : 1;
+ U32 saving : 1;
+ U32 reserved3 : 1;
+ U32 max_number_routed_sas_addresses : 16;
+
+ SCI_SAS_ADDRESS_T active_zone_manager_sas_address;
+
+ U16 zone_lock_inactivity_time_limit;
+ U16 reserved4;
+
+ U8 reserved5;
+ U8 first_enclosure_connector_element_index;
+ U8 number_of_enclosure_connector_element_indices;
+ U8 reserved6;
+
+ U32 reserved7 : 7;
+ U32 reduced_functionality : 1;
+ U32 time_to_reduce_functionality : 8;
+ U32 initial_time_to_reduce_functionality : 8;
+ U8 max_reduced_functionality_time;
+
+ U16 last_self_config_status_descriptor_index;
+ U16 max_number_of_stored_self_config_status_descriptors;
+
+ U16 last_phy_event_list_descriptor_index;
+ U16 max_number_of_stored_phy_event_list_descriptors;
+ } sas2;
+
+} SMP_RESPONSE_REPORT_GENERAL_LONG_T;
+
+/**
+ * @struct SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION
+ * @brief This structure depicts the SMP report manufacturer
+ * information for expander devices. It adheres to the
+ * SAS-2.1 specification.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification
+ * Application layer section on SMP.
+ */
+typedef struct SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION
+{
+ U32 expander_change_count : 16; // bytes 4-5
+ U32 reserved1 : 16;
+
+ U32 sas1_1_format : 1;
+ U32 reserved2 : 31;
+
+ U8 vendor_id[8];
+ U8 product_id[16];
+ U8 product_revision_level[4];
+ U8 component_vendor_id[8];
+ U8 component_id[2];
+ U8 component_revision_level;
+ U8 reserved3;
+ U8 vendor_specific[8];
+
+} SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T;
+
+#define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52
+#define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE 116
+
+/**
+ * @struct SMP_DISCOVER_RESPONSE_PROTOCOLS
+ * @brief This structure depicts the discover response where the
+ * supported protocols by the remote phy are specified.
+ * @note For specific information on each of these
+ * individual fields please reference the SAS specification
+ * Link layer section on address frames.
+ */
+typedef struct SMP_DISCOVER_RESPONSE_PROTOCOLS
+{
+ union
+ {
+ struct
+ {
+ U16 attached_sata_host : 1;
+ U16 attached_smp_initiator : 1;
+ U16 attached_stp_initiator : 1;
+ U16 attached_ssp_initiator : 1;
+ U16 reserved3 : 4;
+ U16 attached_sata_device : 1;
+ U16 attached_smp_target : 1;
+ U16 attached_stp_target : 1;
+ U16 attached_ssp_target : 1;
+ U16 reserved4 : 3;
+ U16 attached_sata_port_selector : 1;
+ } bits;
+
+ U16 all;
+ } u;
+
+} SMP_DISCOVER_RESPONSE_PROTOCOLS_T;
+
+/**
+ * @struct SMP_RESPONSE_DISCOVER_FORMAT
+ * @brief This structure defines the SMP phy discover response format.
+ * It handles both SAS1.1 and SAS 2 definitions. The unions
+ * indicate locations where the SAS specification versions
+ * differ from one another.
+ */
+typedef struct SMP_RESPONSE_DISCOVER
+{
+
+ union
+ {
+ struct
+ {
+ U8 reserved[2];
+ } sas1_1;
+
+ struct
+ {
+ U16 expander_change_count;
+ } sas2;
+
+ } u1;
+
+ U8 reserved1[3];
+ U8 phy_identifier;
+ U8 reserved2[2];
+
+ union
+ {
+ struct
+ {
+ U16 reserved1 : 4;
+ U16 attached_device_type : 3;
+ U16 reserved2 : 1;
+ U16 negotiated_physical_link_rate : 4;
+ U16 reserved3 : 4;
+ } sas1_1;
+
+ struct
+ {
+ U16 attached_reason : 4;
+ U16 attached_device_type : 3;
+ U16 reserved2 : 1;
+ U16 negotiated_logical_link_rate : 4;
+ U16 reserved3 : 4;
+ } sas2;
+
+ } u2;
+
+ SMP_DISCOVER_RESPONSE_PROTOCOLS_T protocols;
+ SCI_SAS_ADDRESS_T sas_address;
+ SCI_SAS_ADDRESS_T attached_sas_address;
+
+ U8 attached_phy_identifier;
+
+ union
+ {
+ struct
+ {
+ U8 reserved;
+ } sas1_1;
+
+ struct
+ {
+ U8 attached_break_reply_capable : 1;
+ U8 attached_requested_inside_zpsds : 1;
+ U8 attached_inside_zpsds_persistent : 1;
+ U8 reserved1 : 5;
+ } sas2;
+
+ } u3;
+
+ U8 reserved_for_identify[6];
+
+ U32 hardware_min_physical_link_rate : 4;
+ U32 programmed_min_physical_link_rate : 4;
+ U32 hardware_max_physical_link_rate : 4;
+ U32 programmed_max_physical_link_rate : 4;
+ U32 phy_change_count : 8;
+ U32 partial_pathway_timeout_value : 4;
+ U32 reserved5 : 3;
+ U32 virtual_phy : 1;
+
+ U32 routing_attribute : 4;
+ U32 reserved6 : 4;
+ U32 connector_type : 7;
+ U32 reserved7 : 1;
+ U32 connector_element_index : 8;
+ U32 connector_physical_link : 8;
+
+ U16 reserved8;
+ U16 vendor_specific;
+
+ union
+ {
+ struct
+ {
+ /**
+ * In the SAS 1.1 specification this structure ends after 52 bytes.
+ * As a result, the contents of this field should never have a
+ * real value. It is undefined.
+ */
+ U8 undefined[SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE
+ - SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE];
+ } sas1_1;
+
+ struct
+ {
+ SCI_SAS_ADDRESS_T attached_device_name;
+
+ U32 zoning_enabled : 1;
+ U32 inside_zpsds : 1;
+ U32 zone_group_persistent : 1;
+ U32 reserved1 : 1;
+ U32 requested_inside_zpsds : 1;
+ U32 inside_zpsds_persistent : 1;
+ U32 requested_inside_zpsds_changed_by_expander : 1;
+ U32 reserved2 : 1;
+ U32 reserved_for_zoning_fields : 16;
+ U32 zone_group : 8;
+
+ U8 self_configuration_status;
+ U8 self_configuration_levels_completed;
+ U16 reserved_for_self_config_fields;
+
+ SCI_SAS_ADDRESS_T self_configuration_sas_address;
+
+ U32 programmed_phy_capabilities;
+ U32 current_phy_capabilities;
+ U32 attached_phy_capabilities;
+
+ U32 reserved3;
+
+ U32 reserved4 : 16;
+ U32 negotiated_physical_link_rate : 4;
+ U32 reason : 4;
+ U32 hardware_muxing_supported : 1;
+ U32 negotiated_ssc : 1;
+ U32 reserved5 : 6;
+
+ U32 default_zoning_enabled : 1;
+ U32 reserved6 : 1;
+ U32 default_zone_group_persistent : 1;
+ U32 reserved7 : 1;
+ U32 default_requested_inside_zpsds : 1;
+ U32 default_inside_zpsds_persistent : 1;
+ U32 reserved8 : 2;
+ U32 reserved9 : 16;
+ U32 default_zone_group : 8;
+
+ U32 saved_zoning_enabled : 1;
+ U32 reserved10 : 1;
+ U32 saved_zone_group_persistent : 1;
+ U32 reserved11 : 1;
+ U32 saved_requested_inside_zpsds : 1;
+ U32 saved_inside_zpsds_persistent : 1;
+ U32 reserved12 : 18;
+ U32 saved_zone_group : 8;
+
+ U32 reserved14 : 2;
+ U32 shadow_zone_group_persistent : 1;
+ U32 reserved15 : 1;
+ U32 shadow_requested_inside_zpsds : 1;
+ U32 shadow_inside_zpsds_persistent : 1;
+ U32 reserved16 : 18;
+ U32 shadow_zone_group : 8;
+
+ U8 device_slot_number;
+ U8 device_slot_group_number;
+ U8 device_slot_group_output_connector[6];
+ } sas2;
+
+ } u4;
+
+} SMP_RESPONSE_DISCOVER_T;
+
+/**
+ * @struct SMP_RESPONSE_REPORT_PHY_SATA
+ * @brief This structure depicts the contents of the SAS SMP REPORT
+ * PHY SATA frame. For specific information on each of these
+ * individual fields please reference the SAS specification Link
+ * layer section on address frames.
+ */
+typedef struct SMP_RESPONSE_REPORT_PHY_SATA
+{
+ U32 ignored_byte_4_7; // bytes 4-7
+
+ U32 affiliations_valid:1;
+ U32 affiliations_supported:1;
+ U32 reserved_byte11:6; // byte 11
+ U32 ignored_byte10:8; // byte 10
+ U32 phy_identifier:8; // byte 9
+ U32 reserved_byte_8:8; // byte 8
+
+ U32 reserved_12_15;
+ U32 stp_sas_address[2];
+ U8 device_to_host_fis[20];
+ U32 reserved_44_47;
+ U32 affiliated_stp_initiator_sas_address[2];
+
+} SMP_RESPONSE_REPORT_PHY_SATA_T;
+
+typedef struct SMP_RESPONSE_VENDOR_SPECIFIC
+{
+ U8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
+}SMP_RESPONSE_VENDOR_SPECIFIC_T;
+
+typedef union SMP_RESPONSE_BODY
+{
+ SMP_RESPONSE_REPORT_GENERAL_T report_general;
+ SMP_RESPONSE_REPORT_MANUFACTURER_INFORMATION_T report_manufacturer_information;
+ SMP_RESPONSE_DISCOVER_T discover;
+ SMP_RESPONSE_REPORT_PHY_SATA_T report_phy_sata;
+ SMP_RESPONSE_VENDOR_SPECIFIC_T vendor_specific_response;
+} SMP_RESPONSE_BODY_T;
+
+/**
+ * @struct SMP_RESPONSE
+ * @brief This structure simply unionizes the existing response
+ * structures into a common response type.
+ */
+typedef struct _SMP_RESPONSE
+{
+ SMP_RESPONSE_HEADER_T header;
+
+ SMP_RESPONSE_BODY_T response;
+
+} SMP_RESPONSE_T;
+
+// SMP Request Functions
+#define SMP_FUNCTION_REPORT_GENERAL 0x00
+#define SMP_FUNCTION_REPORT_MANUFACTURER_INFORMATION 0x01
+#define SMP_FUNCTION_DISCOVER 0x10
+#define SMP_FUNCTION_REPORT_PHY_ERROR_LOG 0x11
+#define SMP_FUNCTION_REPORT_PHY_SATA 0x12
+#define SMP_FUNCTION_REPORT_ROUTE_INFORMATION 0X13
+#define SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION 0X90
+#define SMP_FUNCTION_PHY_CONTROL 0x91
+#define SMP_FUNCTION_PHY_TEST 0x92
+
+#define SMP_FRAME_TYPE_REQUEST 0x40
+#define SMP_FRAME_TYPE_RESPONSE 0x41
+
+#define PHY_OPERATION_NOP 0x00
+#define PHY_OPERATION_LINK_RESET 0x01
+#define PHY_OPERATION_HARD_RESET 0x02
+#define PHY_OPERATION_DISABLE 0x03
+#define PHY_OPERATION_CLEAR_ERROR_LOG 0x05
+#define PHY_OPERATION_CLEAR_AFFILIATION 0x06
+
+#define NPLR_PHY_ENABLED_UNK_LINK_RATE 0x00
+#define NPLR_PHY_DISABLED 0x01
+#define NPLR_PHY_ENABLED_SPD_NEG_FAILED 0x02
+#define NPLR_PHY_ENABLED_SATA_HOLD 0x03
+#define NPLR_PHY_ENABLED_1_5G 0x08
+#define NPLR_PHY_ENABLED_3_0G 0x09
+
+// SMP Function Result values.
+#define SMP_RESULT_FUNCTION_ACCEPTED 0x00
+#define SMP_RESULT_UNKNOWN_FUNCTION 0x01
+#define SMP_RESULT_FUNCTION_FAILED 0x02
+#define SMP_RESULT_INVALID_REQUEST_FRAME_LEN 0x03
+#define SMP_RESULT_INAVALID_EXPANDER_CHANGE_COUNT 0x04
+#define SMP_RESULT_BUSY 0x05
+#define SMP_RESULT_INCOMPLETE_DESCRIPTOR_LIST 0x06
+#define SMP_RESULT_PHY_DOES_NOT_EXIST 0x10
+#define SMP_RESULT_INDEX_DOES_NOT_EXIST 0x11
+#define SMP_RESULT_PHY_DOES_NOT_SUPPORT_SATA 0x12
+#define SMP_RESULT_UNKNOWN_PHY_OPERATION 0x13
+#define SMP_RESULT_UNKNOWN_PHY_TEST_FUNCTION 0x14
+#define SMP_RESULT_PHY_TEST_IN_PROGRESS 0x15
+#define SMP_RESULT_PHY_VACANT 0x16
+
+/* Attached Device Types */
+#define SMP_NO_DEVICE_ATTACHED 0
+#define SMP_END_DEVICE_ONLY 1
+#define SMP_EDGE_EXPANDER_DEVICE 2
+#define SMP_FANOUT_EXPANDER_DEVICE 3
+
+/* Expander phy routine attribute */
+#define DIRECT_ROUTING_ATTRIBUTE 0
+#define SUBTRACTIVE_ROUTING_ATTRIBUTE 1
+#define TABLE_ROUTING_ATTRIBUTE 2
+
+#endif // _INTEL_SAS_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_sat.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_sat.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,94 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SAT_H_
+#define _SAT_H_
+
+/**
+ * @file
+ * @brief This file contains constants and constructs defined in the SCSI
+ * to ATA Translation (SAT) T10 standard. For more information please
+ * refer to www.t10.org.
+ */
+
+/**
+ * @name SAT_PROTOCOLS
+ *
+ * These constants indicate the various protocol values that can be supported
+ * in a SAT translator.
+ */
+/*@{*/
+#define SAT_PROTOCOL_ATA_HARD_RESET 0
+#define SAT_PROTOCOL_SOFT_RESET 1
+#define SAT_PROTOCOL_NON_DATA 3
+#define SAT_PROTOCOL_PIO_DATA_IN 4
+#define SAT_PROTOCOL_PIO_DATA_OUT 5
+#define SAT_PROTOCOL_DMA 6
+#define SAT_PROTOCOL_DMA_QUEUED 7
+#define SAT_PROTOCOL_DEVICE_DIAGNOSTIC 8
+#define SAT_PROTOCOL_DEVICE_RESET 9
+#define SAT_PROTOCOL_UDMA_DATA_IN 10
+#define SAT_PROTOCOL_UDMA_DATA_OUT 11
+#define SAT_PROTOCOL_FPDMA 12
+#define SAT_PROTOCOL_RETURN_RESPONSE_INFO 15
+
+#define SAT_PROTOCOL_PACKET 0x10
+#define SAT_PROTOCOL_PACKET_NON_DATA (SAT_PROTOCOL_PACKET | 0x0)
+#define SAT_PROTOCOL_PACKET_DMA_DATA_IN (SAT_PROTOCOL_PACKET | 0x1)
+#define SAT_PROTOCOL_PACKET_DMA_DATA_OUT (SAT_PROTOCOL_PACKET | 0x2)
+#define SAT_PROTOCOL_PACKET_PIO_DATA_IN (SAT_PROTOCOL_PACKET | 0x3)
+#define SAT_PROTOCOL_PACKET_PIO_DATA_OUT (SAT_PROTOCOL_PACKET | 0x4)
+/*@}*/
+
+#endif // _SAT_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_sata.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_sata.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,284 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATA_H_
+#define _SATA_H_
+
+#include <dev/isci/types.h>
+
+/**
+ * @file
+ *
+ * @brief This file defines all of the SATA releated constants, enumerations,
+ * and types. Please note that this file does not necessarily contain
+ * an exhaustive list of all contants and commands.
+ */
+
+/**
+ * @name SATA FIS Types
+ *
+ * These constants depict the various SATA FIS types devined in the serial ATA
+ * specification.
+ */
+/*@{*/
+#define SATA_FIS_TYPE_REGH2D 0x27
+#define SATA_FIS_TYPE_REGD2H 0x34
+#define SATA_FIS_TYPE_SETDEVBITS 0xA1
+#define SATA_FIS_TYPE_DMA_ACTIVATE 0x39
+#define SATA_FIS_TYPE_DMA_SETUP 0x41
+#define SATA_FIS_TYPE_BIST_ACTIVATE 0x58
+#define SATA_FIS_TYPE_PIO_SETUP 0x5F
+#define SATA_FIS_TYPE_DATA 0x46
+/*@}*/
+
+#define SATA_REGISTER_FIS_SIZE 0x20
+
+/**
+ * @struct SATA_FIS_HEADER
+ *
+ * @brief This is the common definition for a SATA FIS Header word. A
+ * different header word is defined for any FIS type that does not use
+ * the standard header.
+ */
+typedef struct SATA_FIS_HEADER
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved :1;
+ U32 direction_flag :1; // direction
+ U32 interrupt_flag :1;
+ U32 command_flag :1; // command, auto_activate, or notification
+ U32 status :8;
+ U32 error :8;
+} SATA_FIS_HEADER_T;
+
+
+/**
+ * @struct SATA_FIS_REG_H2D
+ *
+ * @brief This is the definition for a SATA Host to Device Register FIS.
+ */
+typedef struct SATA_FIS_REG_H2D
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved0 :3;
+ U32 command_flag :1;
+ U32 command :8;
+ U32 features :8;
+ U32 lba_low :8; // word 1
+ U32 lba_mid :8;
+ U32 lba_high :8;
+ U32 device :8;
+ U32 lba_low_exp :8; // word 2
+ U32 lba_mid_exp :8;
+ U32 lba_high_exp :8;
+ U32 features_exp :8;
+ U32 sector_count :8; // word 3
+ U32 sector_count_exp :8;
+ U32 reserved1 :8;
+ U32 control :8;
+ U32 reserved2; // word 4
+} SATA_FIS_REG_H2D_T;
+
+/**
+ * @struct SATA_FIS_REG_D2H
+ *
+ * @brief SATA Device To Host FIS
+ */
+typedef struct SATA_FIS_REG_D2H
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved0 :2;
+ U32 irq :1;
+ U32 reserved1 :1;
+ U32 status :8;
+ U32 error :8;
+ U8 lba_low; // word 1
+ U8 lba_mid;
+ U8 lba_high;
+ U8 device;
+ U8 lba_low_exp; // word 2
+ U8 lba_mid_exp;
+ U8 lba_high_exp;
+ U8 reserved;
+ U8 sector_count; // word 3
+ U8 sector_count_exp;
+ U16 reserved2;
+ U32 reserved3;
+} SATA_FIS_REG_D2H_T;
+
+/**
+ * Status field bit definitions
+ */
+#define SATA_FIS_STATUS_DEVBITS_MASK (0x77)
+
+/**
+ * @struct SATA_FIS_SET_DEV_BITS
+ *
+ * @brief SATA Set Device Bits FIS
+ */
+typedef struct SATA_FIS_SET_DEV_BITS
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved0 :2;
+ U32 irq :1;
+ U32 notification :1;
+ U32 status_low :4;
+ U32 status_high :4;
+ U32 error :8;
+ U32 s_active; // word 1
+} SATA_FIS_SET_DEV_BITS_T;
+
+/**
+ * @struct SATA_FIS_DMA_ACTIVATE
+ *
+ * @brief SATA DMA Activate FIS
+ */
+typedef struct SATA_FIS_DMA_ACTIVATE
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved0 :24;
+} SATA_FIS_DMA_ACTIVATE_T;
+
+/**
+ * The lower 5 bits in the DMA Buffer ID Low field of the DMA Setup
+ * are used to communicate the command tag.
+ */
+#define SATA_DMA_SETUP_TAG_ENABLE 0x1F
+
+#define SATA_DMA_SETUP_AUTO_ACT_ENABLE 0x80
+
+/**
+ * @struct SATA_FIS_DMA_SETUP
+ *
+ * @brief SATA DMA Setup FIS
+ */
+typedef struct SATA_FIS_DMA_SETUP
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved_00 :1;
+ U32 direction :1;
+ U32 irq :1;
+ U32 auto_activate :1;
+ U32 reserved_01 :16;
+ U32 dma_buffer_id_low; // word 1
+ U32 dma_buffer_id_high; // word 2
+ U32 reserved0; // word 3
+ U32 dma_buffer_offset; // word 4
+ U32 dma_transfer_count; // word 5
+ U32 reserved1; // word 6
+} SATA_FIS_DMA_SETUP_T;
+
+/**
+ * @struct SATA_FIS_BIST_ACTIVATE
+ *
+ * @brief SATA BIST Activate FIS
+ */
+typedef struct SATA_FIS_BIST_ACTIVATE
+{
+ U32 fis_type :8; // word 0
+ U32 reserved0 :8;
+ U32 pattern_definition :8;
+ U32 reserved1 :8;
+ U32 data1; // word 1
+ U32 data2; // word 1
+} SATA_FIS_BIST_ACTIVATE_T;
+
+/*
+ * SATA PIO Setup FIS
+ */
+typedef struct SATA_FIS_PIO_SETUP
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved_00 :1;
+ U32 direction :1;
+ U32 irq :1;
+ U32 reserved_01 :1;
+ U32 status :8;
+ U32 error :8;
+ U32 lba_low :8; // word 1
+ U32 lba_mid :8;
+ U32 lba_high :8;
+ U32 device :8;
+ U32 lba_low_exp :8; // word 2
+ U32 lba_mid_exp :8;
+ U32 lba_high_exp :8;
+ U32 reserved :8;
+ U32 sector_count :8; // word 3
+ U32 sector_count_exp :8;
+ U32 reserved1 :8;
+ U32 ending_status :8;
+ U32 transfter_count :16; // word 4
+ U32 reserved3 :16;
+} SATA_FIS_PIO_SETUP_T;
+
+/**
+ * @struct SATA_FIS_DATA
+ *
+ * @brief SATA Data FIS
+ */
+typedef struct SATA_FIS_DATA
+{
+ U32 fis_type :8; // word 0
+ U32 pm_port :4;
+ U32 reserved0 :24;
+ U8 data[4]; // word 1
+} SATA_FIS_DATA_T;
+
+#endif // _SATA_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/intel_scsi.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/intel_scsi.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,540 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file defines all of the SCSI related constants, enumerations,
+ * and types. Please note that this file does not necessarily contain
+ * an exhaustive list of all constants, commands, sub-commands, etc.
+ */
+
+#ifndef _SCSI_H__
+#define _SCSI_H__
+
+
+//******************************************************************************
+//* C O N S T A N T S A N D M A C R O S
+//******************************************************************************
+
+/**
+ * @enum _SCSI_TASK_MGMT_REQUEST_CODES
+ *
+ * @brief This enumberation contains the constants to be used for SCSI task
+ * management request codes. SAM does not specify any particular
+ * values for these codes so constants used here are the same as
+ * those specified in SAS.
+ */
+typedef enum _SCSI_TASK_MGMT_REQUEST_CODES
+{
+ SCSI_TASK_REQUEST_ABORT_TASK = 0x01,
+ SCSI_TASK_REQUEST_ABORT_TASK_SET = 0x02,
+ SCSI_TASK_REQUEST_CLEAR_TASK_SET = 0x04,
+ SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET = 0x08,
+ SCSI_TASK_REQUEST_I_T_NEXUS_RESET = 0x10,
+ SCSI_TASK_REQUEST_CLEAR_ACA = 0x40,
+ SCSI_TASK_REQUEST_QUERY_TASK = 0x80,
+ SCSI_TASK_REQUEST_QUERY_TASK_SET = 0x81,
+ SCSI_TASK_REQUEST_QUERY_UNIT_ATTENTION = 0x82,
+
+} SCSI_TASK_MGMT_REQUEST_CODES;
+
+/**
+ * @enum _SCSI_TASK_MGMT_RESPONSE_CODES
+ *
+ * @brief This enumeration contains all of the SCSI task management response
+ * codes.
+ */
+typedef enum _SCSI_TASK_MGMT_RESPONSE_CODES
+{
+ SCSI_TASK_MGMT_FUNC_COMPLETE = 0,
+ SCSI_INVALID_FRAME = 2,
+ SCSI_TASK_MGMT_FUNC_NOT_SUPPORTED = 4,
+ SCSI_TASK_MGMT_FUNC_FAILED = 5,
+ SCSI_TASK_MGMT_FUNC_SUCCEEDED = 8,
+ SCSI_INVALID_LUN = 9
+} SCSI_TASK_MGMT_RESPONSE_CODES;
+
+/**
+ * @enum _SCSI_SENSE_RESPONSE_CODE
+ *
+ * @brief this enumeration depicts the types of sense data responses as
+ * per SPC-3.
+ */
+typedef enum _SCSI_SENSE_RESPONSE_CODE
+{
+ SCSI_FIXED_CURRENT_RESPONSE_CODE = 0x70,
+ SCSI_FIXED_DEFERRED_RESPONSE_CODE = 0x71,
+ SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE = 0x72,
+ SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE = 0x73
+
+} SCSI_SENSE_RESPONSE_CODE;
+
+/**
+ * @enum _SCSI_SENSE_DATA_DESCRIPTOR_TYPE
+ *
+ * @brief this enumeration depicts the types of sense data descriptor as
+ * per SPC-4.
+ */
+typedef enum _SCSI_SENSE_DATA_DESCRIPTOR_TYPE
+{
+ SCSI_INFORMATION_DESCRIPTOR_TYPE = 0x00,
+ SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE = 0x01,
+ SCSI_KEY_SPECIFIC_DESCRIPTOR_TYPE = 0x02,
+ SCSI_FIELD_REPLACEABLE_UNIT_DESCRIPTOR_TYPE = 0x03,
+ SCSI_STREAM_CMD_DESCRIPTOR_TYPE = 0x04,
+ SCSI_BLOCK_DESCRIPTOR_TYPE = 0x05,
+ SCSI_OSD_OBJ_IDENTIFICATION_DESCRIPTOR_TYPE = 0x06,
+ SCSI_OSC_RESPONSE_INTEGRITY_DESCRIPTOR_TYPE = 0x07,
+ SCSI_OSD_ATTR_IDENTIFICATION_DESCRIPTOR_TYPE = 0x08,
+ SCSI_ATA_STATUS_RETURN_DESCRIPTOR_TYPE = 0x09,
+ SCSI_PROGRESS_INDICATION_DESCRIPTOR_TYPE = 0x0a,
+ SCSI_USER_DATA_SEGEMNT_REF_DESCRIPTOR_TYPE = 0x0b
+} SCSI_SENSE_DATA_DESCRIPTOR_TYPE;
+
+#define SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH 0x0a
+#define SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH 0x0c
+#define SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH 0x0a
+#define SCSI_INFORMATION_DESCRIPTOR_LENGTH 0x0c
+#define SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH 0x2
+#define SCSI_BLOCK_DESCRIPTOR_LENGTH 0x4
+
+#define SCSI_SENSE_DATA_DESC_BIT 0x01
+
+// This constant represents the valid bit located in byte 0 of a FIXED
+// format sense data.
+#define SCSI_FIXED_SENSE_DATA_VALID_BIT 0x80
+
+#define SCSI_FIXED_SENSE_DATA_BASE_LENGTH 18
+
+// This value is used in the DATAPRES field of the SCSI Response IU.
+#define SCSI_RESPONSE_DATA_PRES_SENSE_DATA 0x02
+
+/**
+ * @name SCSI_SENSE_KEYS
+ *
+ * These constants delineate all of the SCSI protocol sense key constants
+ */
+/*@{*/
+#define SCSI_SENSE_NO_SENSE 0x00
+#define SCSI_SENSE_RECOVERED_ERROR 0x01
+#define SCSI_SENSE_NOT_READY 0x02
+#define SCSI_SENSE_MEDIUM_ERROR 0x03
+#define SCSI_SENSE_HARDWARE_ERROR 0x04
+#define SCSI_SENSE_ILLEGAL_REQUEST 0x05
+#define SCSI_SENSE_UNIT_ATTENTION 0x06
+#define SCSI_SENSE_DATA_PROTECT 0x07
+#define SCSI_SENSE_BLANK_CHECK 0x08
+#define SCSI_SENSE_VENDOR_SPECIFIC 0x09
+#define SCSI_SENSE_COPY_ABORTED 0x0A
+#define SCSI_SENSE_ABORTED_COMMAND 0x0B
+#define SCSI_SENSE_VOLUME_OVERFLOW 0x0D
+#define SCSI_SENSE_MISCOMPARE 0x0E
+/*@}*/
+
+/**
+ * @name SCSI_ADDITIONAL_SENSE_CODES
+ *
+ * These constants delineate all of the SCSI protocol additional sense
+ * code constants.
+ */
+/*@{*/
+#define SCSI_ASC_NO_ADDITIONAL_SENSE 0x00
+#define SCSI_ASC_INITIALIZING_COMMAND_REQUIRED 0x04
+#define SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS 0x04
+#define SCSI_ASC_LUN_FORMAT_IN_PROGRESS 0x04
+#define SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION 0x05
+#define SCSI_ASC_UNRECOVERED_READ_ERROR 0x11
+#define SCSI_ASC_INVALID_COMMAND_OPERATION_CODE 0x20
+#define SCSI_ASC_LBA_OUT_OF_RANGE 0x21
+#define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24
+#define SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED 0x25
+#define SCSI_ASC_INVALID_FIELD_IN_PARM_LIST 0x26
+#define SCSI_ASC_WRITE_PROTECTED 0x27
+#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28
+#define SCSI_ASC_MEDIUM_FORMAT_CORRUPTED 0x31
+#define SCSI_ASC_ENCLOSURE_SERVICES_UNAVAILABLE 0x35
+#define SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED 0x39
+#define SCSI_ASC_MEDIUM_NOT_PRESENT 0x3A
+#define SCSI_ASC_INTERNAL_TARGET_FAILURE 0x44
+#define SCSI_ASC_IU_CRC_ERROR_DETECTED 0x47
+#define SCSI_ASC_MEDIUM_REMOVAL_REQUEST 0x5A
+#define SCSI_ASC_COMMAND_SEQUENCE_ERROR 0x2C
+#define SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED 0x53
+#define SCSI_ASC_HARDWARE_IMPENDING_FAILURE 0x5D
+#define SCSI_ASC_POWER_STATE_CHANGE 0x5E
+#define SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT 0x40
+#define SCSI_ASC_LOGICAL_UNIT_FAILED 0x4C
+#define SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED 0x67
+#define SCSI_ASC_MICROCODE_HAS_CHANGED 0x3F
+/*@}*/
+
+/**
+ * @name SCSI_ADDITIONAL_SENSE_CODE_QUALIFIERS
+ *
+ * This enumeration contains all of the used SCSI protocol additional
+ * sense code qualifier constants.
+ */
+/*@{*/
+#define SCSI_ASCQ_NO_ADDITIONAL_SENSE 0x00
+#define SCSI_ASCQ_INVALID_FIELD_IN_CDB 0x00
+#define SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST 0x00
+#define SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION 0x00
+#define SCSI_ASCQ_INTERNAL_TARGET_FAILURE 0x00
+#define SCSI_ASCQ_LBA_OUT_OF_RANGE 0x00
+#define SCSI_ASCQ_MEDIUM_NOT_PRESENT 0x00
+#define SCSI_ASCQ_NOT_READY_TO_READY_CHANGE 0x00
+#define SCSI_ASCQ_WRITE_PROTECTED 0x00
+#define SCSI_ASCQ_UNRECOVERED_READ_ERROR 0x00
+#define SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED 0x00
+#define SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE 0x00
+#define SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST 0x01
+#define SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02
+#define SCSI_ASCQ_IU_CRC_ERROR_DETECTED 0x03
+#define SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS 0x04
+#define SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS 0x09
+#define SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE 0x10
+#define SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND 0x03
+#define SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND 0x04
+#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE 0x42
+#define SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY 0x43
+#define SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED 0x0B
+#define SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL 0x04
+#define SCSI_ASCQ_ATA_PASS_THROUGH_INFORMATION_AVAILABLE 0x1D
+#define SCSI_ASCQ_MICROCODE_HAS_CHANGED 0x01
+/*@}*/
+
+/**
+ * @name SCSI_STATUS_CODES
+ *
+ * These constants define all of the used SCSI status values.
+ */
+/*@{*/
+#define SCSI_STATUS_GOOD 0x00
+#define SCSI_STATUS_CHECK_CONDITION 0x02
+#define SCSI_STATUS_CONDITION_MET 0x04
+#define SCSI_STATUS_BUSY 0x08
+#define SCSI_STATUS_TASKFULL 0x28
+#define SCSI_STATUS_ACA 0x30
+#define SCSI_STATUS_ABORT 0x40
+/*@}*/
+
+/**
+ * @name SCSI_OPERATION_CODES
+ *
+ * These constants delineate all of the SCSI command/operation codes.
+ */
+/*@{*/
+#define SCSI_INQUIRY 0x12
+#define SCSI_READ_CAPACITY_10 0x25
+#define SCSI_SERVICE_ACTION_IN_16 0x9E
+#define SCSI_TEST_UNIT_READY 0x00
+#define SCSI_START_STOP_UNIT 0x1B
+#define SCSI_SYNCHRONIZE_CACHE_10 0x35
+#define SCSI_SYNCHRONIZE_CACHE_16 0x91
+#define SCSI_REQUEST_SENSE 0x03
+#define SCSI_REPORT_LUNS 0xA0
+#define SCSI_REASSIGN_BLOCKS 0x07
+#define SCSI_READ_6 0x08
+#define SCSI_READ_10 0x28
+#define SCSI_READ_12 0xA8
+#define SCSI_READ_16 0x88
+#define SCSI_WRITE_6 0x0A
+#define SCSI_WRITE_10 0x2A
+#define SCSI_WRITE_12 0xAA
+#define SCSI_WRITE_16 0x8A
+#define SCSI_VERIFY_10 0x2F
+#define SCSI_VERIFY_12 0xAF
+#define SCSI_VERIFY_16 0x8F
+#define SCSI_SEEK_6 0x01
+#define SCSI_SEEK_10 0x02
+#define SCSI_WRITE_VERIFY 0x2E
+#define SCSI_FORMAT_UNIT 0x04
+#define SCSI_READ_BUFFER 0x3C
+#define SCSI_WRITE_BUFFER 0x3B
+#define SCSI_SEND_DIAGNOSTIC 0x1D
+#define SCSI_RECEIVE_DIAGNOSTIC 0x1C
+#define SCSI_MODE_SENSE_6 0x1A
+#define SCSI_MODE_SENSE_10 0x5A
+#define SCSI_MODE_SELECT_6 0x15
+#define SCSI_MODE_SELECT_10 0x55
+#define SCSI_MAINTENANCE_IN 0xA3
+#define SCSI_LOG_SENSE 0x4D
+#define SCSI_LOG_SELECT 0x4C
+#define SCSI_RESERVE_6 0x16
+#define SCSI_RESERVE_10 0x56
+#define SCSI_RELEASE_6 0x17
+#define SCSI_RELEASE_10 0x57
+#define SCSI_ATA_PASSTHRU_12 0xA1
+#define SCSI_ATA_PASSTHRU_16 0x85
+#define SCSI_WRITE_LONG_10 0x3F
+#define SCSI_WRITE_LONG_16 0x9F
+#define SCSI_PERSISTENT_RESERVE_IN 0x5E
+#define SCSI_PERSISTENT_RESERVE_OUT 0x5F
+#define SCSI_SECURITY_PROTOCOL_IN 0xA2
+#define SCSI_SECURITY_PROTOCOL_OUT 0xB5
+#define SCSI_UNMAP 0x42
+#define SCSI_WRITE_AND_VERIFY_10 0x2E
+#define SCSI_WRITE_AND_VERIFY_12 0xAE
+#define SCSI_WRITE_AND_VERIFY_16 0x8E
+/*@}*/
+
+/**
+ * @name SCSI_SERVICE_ACTION_IN_CODES
+ *
+ * Service action in operations.
+ */
+/*@{*/
+#define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16 0x10
+/*@}*/
+
+/**
+*
+* Service action mask.
+ */
+/*@{*/
+#define SCSI_SERVICE_ACTION_MASK 0x1f
+/*@}*/
+
+/**
+ * @name SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES
+ *
+ * MAINTENANCE IN service action codes.
+ */
+/*@{*/
+#define SCSI_REPORT_TASK_MGMT 0x0D
+#define SCSI_REPORT_OP_CODES 0x0C
+/*@}*/
+
+/**
+ * @name SCSI_MODE_PAGE_CONTROLS
+ *
+ * These constants delineate all of the used SCSI Mode Page control
+ * values.
+ */
+/*@{*/
+#define SCSI_MODE_SENSE_PC_CURRENT 0x0
+#define SCSI_MODE_SENSE_PC_CHANGEABLE 0x1
+#define SCSI_MODE_SENSE_PC_DEFAULT 0x2
+#define SCSI_MODE_SENSE_PC_SAVED 0x3
+/*@}*/
+
+#define SCSI_MODE_SENSE_PC_SHIFT 0x06
+#define SCSI_MODE_SENSE_PAGE_CODE_ENABLE 0x3F
+#define SCSI_MODE_SENSE_DBD_ENABLE 0x08
+#define SCSI_MODE_SENSE_LLBAA_ENABLE 0x10
+
+#define SCSI_MODE_PAGE_CONTROL_D_SENSE_DISABLE 0x0
+#define SCSI_MODE_PAGE_CONTROL_D_SENSE_ENABLE 0x1
+/**
+ * @name SCSI_MODE_PAGE_CODES
+ *
+ * These constants delineate all of the used SCSI Mode Page codes.
+ */
+/*@{*/
+#define SCSI_MODE_PAGE_READ_WRITE_ERROR 0x01
+#define SCSI_MODE_PAGE_DISCONNECT_RECONNECT 0x02
+#define SCSI_MODE_PAGE_CACHING 0x08
+#define SCSI_MODE_PAGE_CONTROL 0x0A
+#define SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT 0x19
+#define SCSI_MODE_PAGE_POWER_CONDITION 0x1A
+#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL 0x1C
+#define SCSI_MODE_PAGE_ALL_PAGES 0x3F
+/*@}*/
+
+#define SCSI_MODE_SENSE_ALL_SUB_PAGES_CODE 0xFF
+#define SCSI_MODE_SENSE_NO_SUB_PAGES_CODE 0x0
+#define SCSI_MODE_SENSE_PROTOCOL_PORT_NUM_SUBPAGES 0x1
+#define SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT 0x04
+#define SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT 0x20
+#define SCSI_MODE_PAGE_DEXCPT_ENABLE 0x08
+#define SCSI_MODE_SENSE_HEADER_FUA_ENABLE 0x10
+#define SCSI_MODE_PAGE_POWER_CONDITION_STANDBY 0x1
+#define SCSI_MODE_PAGE_POWER_CONDITION_IDLE 0x2
+
+#define SCSI_MODE_SENSE_6_HEADER_LENGTH 4
+#define SCSI_MODE_SENSE_10_HEADER_LENGTH 8
+#define SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH 8
+#define SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH 16
+
+#define SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE 0x08
+#define SCSI_MODE_PAGE_19_SAS_ID 0x6
+#define SCSI_MODE_PAGE_19_SUB1_PAGE_NUM 0x1
+#define SCSI_MODE_PAGE_19_SUB1_PC 0x59
+
+#define SCSI_MODE_HEADER_MEDIUM_TYPE_SBC 0x00
+
+//Mode Select constrains related masks value
+#define SCSI_MODE_SELECT_PF_BIT 0x1
+#define SCSI_MODE_SELECT_PF_MASK 0x10
+#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_BYTE 0x6
+#define SCSI_MODE_SELECT_MODE_PAGE_MRIE_MASK 0x0F
+#define SCSI_MODE_SELECT_MODE_PAGE_SPF_MASK 0x40
+#define SCSI_MODE_SELECT_MODE_PAGE_01_AWRE_MASK 0x80
+#define SCSI_MODE_SELECT_MODE_PAGE_01_ARRE_MASK 0x40
+#define SCSI_MODE_SELECT_MODE_PAGE_01_RC_ERBITS_MASK 0x1F
+#define SCSI_MODE_SELECT_MODE_PAGE_08_FSW_LBCSS_NVDIS 0xC1
+#define SCSI_MODE_SELECT_MODE_PAGE_1C_PERF_TEST 0x84
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_TST_TMF_RLEC 0xF1
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_MODIFIER 0xE0
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP 0x38
+#define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO 0x47
+#define SCSI_MODE_SELECT_MODE_PAGE_D_SENSE 0x4
+
+#define SCSI_CONTROL_BYTE_NACA_BIT_ENABLE 0x04
+#define SCSI_MOVE_FUA_BIT_ENABLE 0x08
+#define SCSI_READ_CAPACITY_PMI_BIT_ENABLE 0x01
+#define SCSI_READ_CAPACITY_10_DATA_LENGTH 8
+#define SCSI_READ_CAPACITY_16_DATA_LENGTH 32
+
+// Inquiry constants
+#define SCSI_INQUIRY_EVPD_ENABLE 0x01
+#define SCSI_INQUIRY_PAGE_CODE_OFFSET 0x02
+#define SCSI_INQUIRY_SUPPORTED_PAGES_PAGE 0x00
+#define SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE 0x80
+#define SCSI_INQUIRY_DEVICE_ID_PAGE 0x83
+#define SCSI_INQUIRY_ATA_INFORMATION_PAGE 0x89
+#define SCSI_INQUIRY_BLOCK_DEVICE_PAGE 0xB1
+#define SCSI_INQUIRY_BLOCK_DEVICE_LENGTH 0x3C
+#define SCSI_INQUIRY_STANDARD_ALLOCATION_LENGTH 0x24 //36
+
+#define SCSI_REQUEST_SENSE_ALLOCATION_LENGTH 0xFC //252
+
+/** Defines the log page codes that are use in gathing Smart data
+*/
+#define SCSI_LOG_PAGE_SUPPORTED_PAGES 0x00
+#define SCSI_LOG_PAGE_INFORMATION_EXCEPTION 0x2F
+#define SCSI_LOG_PAGE_SELF_TEST 0x10
+
+/**
+ * @name SCSI_INQUIRY_VPD
+ *
+ * The following are constants used with vital product data inquiry pages.
+ * Values are already shifted into the proper nibble location.
+ */
+/*@{*/
+#define SCSI_PIV_ENABLE 0x80
+#define SCSI_LUN_ASSOCIATION 0x00
+#define SCSI_TARGET_PORT_ASSOCIATION 0x10
+
+#define SCSI_VEN_UNIQUE_IDENTIFIER_TYPE 0x00
+#define SCSI_NAA_IDENTIFIER_TYPE 0x03
+
+#define SCSI_T10_IDENTIFIER_TYPE 0x01
+#define SCSI_BINARY_CODE_SET 0x01
+#define SCSI_ASCII_CODE_SET 0x02
+#define SCSI_FC_PROTOCOL_IDENTIFIER 0x00
+#define SCSI_SAS_PROTOCOL_IDENTIFIER 0x60
+/*@}*/
+
+#define SCSI_VERIFY_BYTCHK_ENABLED 0x02
+
+#define SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED 0x02
+/**
+ * @name SCSI_START_STOP_UNIT_POWER_CONDITION_CODES
+ *
+ * The following are SCSI Start Stop Unit command Power Condition codes.
+ */
+/*@{*/
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID 0x0
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE 0x1
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE 0x2
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY 0x3
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL 0x7
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL 0xB
+/*@}*/
+
+#define SCSI_START_STOP_UNIT_IMMED_MASK 0x1
+#define SCSI_START_STOP_UNIT_IMMED_SHIFT 0
+
+#define SCSI_START_STOP_UNIT_START_BIT_MASK 0x1
+#define SCSI_START_STOP_UNIT_START_BIT_SHIFT 0
+
+#define SCSI_START_STOP_UNIT_LOEJ_BIT_MASK 0x2
+#define SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT 1
+
+#define SCSI_START_STOP_UNIT_NO_FLUSH_MASK 0x4
+#define SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT 2
+
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK 0xF
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT 0
+
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_MASK 0xF0
+#define SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT 4
+
+#define SCSI_LOG_SENSE_PC_FIELD_MASK 0xC0
+#define SCSI_LOG_SENSE_PC_FIELD_SHIFT 6
+
+#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK 0x3F
+#define SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT 0
+
+/**
+ * @name MRIE - Method of reporting informational exceptions codes
+ */
+/*@{*/
+#define NO_REPORTING_INFO_EXCEPTION_CONDITION 0x0
+#define ASYNCHRONOUS_EVENT_REPORTING 0x1
+#define ESTABLISH_UNIT_ATTENTION_CONDITION 0x2
+#define CONDITIONALLY_GENERATE_RECOVERED_ERROR 0x3
+#define UNCONDITIONALLY_GENERATE_RECOVERED_ERROR 0x4
+#define GENERATE_NO_SENSE 0x5
+#define REPORT_INFO_EXCEPTION_CONDITION_ON_REQUEST 0x6
+/*@}*/
+
+#define SCSI_INFORMATION_EXCEPTION_DEXCPT_BIT 0x08
+
+//Reassign Blocks masks
+#define SCSI_REASSIGN_BLOCKS_LONGLBA_BIT 0x02
+#define SCSI_REASSIGN_BLOCKS_LONGLIST_BIT 0x01
+
+#endif // _SCSI_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,1250 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the method implementations that
+ * can be utilized by a user to perform SCSI-to-ATA Translation.
+ * SATI adheres to the www.t10.org SAT specification.
+ *
+ * For situations where compliance is not observed, the SATI will
+ * return an error indication (most likely INVALID FIELD IN CDB sense data).
+ */
+
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_report_luns.h>
+#include <dev/isci/scil/sati_inquiry.h>
+#include <dev/isci/scil/sati_mode_sense_6.h>
+#include <dev/isci/scil/sati_mode_sense_10.h>
+#include <dev/isci/scil/sati_mode_select.h>
+#include <dev/isci/scil/sati_test_unit_ready.h>
+#include <dev/isci/scil/sati_read_capacity.h>
+#include <dev/isci/scil/sati_read.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_verify.h>
+#include <dev/isci/scil/sati_synchronize_cache.h>
+#include <dev/isci/scil/sati_lun_reset.h>
+#include <dev/isci/scil/sati_start_stop_unit.h>
+#include <dev/isci/scil/sati_request_sense.h>
+#include <dev/isci/scil/sati_write_long.h>
+#include <dev/isci/scil/sati_reassign_blocks.h>
+#include <dev/isci/scil/sati_log_sense.h>
+#include <dev/isci/scil/sati_abort_task_set.h>
+#include <dev/isci/scil/sati_unmap.h>
+#include <dev/isci/scil/sati_passthrough.h>
+#include <dev/isci/scil/sati_write_and_verify.h>
+#include <dev/isci/scil/sati_read_buffer.h>
+#include <dev/isci/scil/sati_write_buffer.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the translation of ATA error register values
+ * into SCSI sense data.
+ * For more information on the parameter passed to this method please
+ * reference the sati_translate_response() method.
+ *
+ * @param[in] error This parameter specifies the contents of the ATA error
+ * register to be translated.
+ *
+ * @return none
+ */
+void sati_translate_error(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 error
+)
+{
+ if (error & ATA_ERROR_REG_NO_MEDIA_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_NOT_READY,
+ SCSI_ASC_MEDIUM_NOT_PRESENT,
+ SCSI_ASCQ_MEDIUM_NOT_PRESENT
+ );
+ }
+ else if (error & ATA_ERROR_REG_MEDIA_CHANGE_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_UNIT_ATTENTION,
+ SCSI_ASC_NOT_READY_TO_READY_CHANGE,
+ SCSI_ASCQ_NOT_READY_TO_READY_CHANGE
+ );
+ }
+ else if (error & ATA_ERROR_REG_MEDIA_CHANGE_REQUEST_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_UNIT_ATTENTION,
+ SCSI_ASC_MEDIUM_REMOVAL_REQUEST,
+ SCSI_ASCQ_MEDIUM_REMOVAL_REQUEST
+ );
+ }
+ else if (error & ATA_ERROR_REG_ID_NOT_FOUND_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_LBA_OUT_OF_RANGE,
+ SCSI_ASCQ_LBA_OUT_OF_RANGE
+ );
+ }
+ else if (error & ATA_ERROR_REG_UNCORRECTABLE_BIT)
+ {
+ //Mark the Sequence state as a read error so more sense data
+ //can be returned later
+ sequence->state = SATI_SEQUENCE_STATE_READ_ERROR;
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_MEDIUM_ERROR,
+ SCSI_ASC_UNRECOVERED_READ_ERROR,
+ SCSI_ASCQ_UNRECOVERED_READ_ERROR
+ );
+ }
+ else if ( (sequence->data_direction == SATI_DATA_DIRECTION_OUT)
+ && (error & ATA_ERROR_REG_WRITE_PROTECTED_BIT) )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_DATA_PROTECT,
+ SCSI_ASC_WRITE_PROTECTED,
+ SCSI_ASCQ_WRITE_PROTECTED
+ );
+ }
+ else if (error & ATA_ERROR_REG_ICRC_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_IU_CRC_ERROR_DETECTED,
+ SCSI_ASCQ_IU_CRC_ERROR_DETECTED
+ );
+ }
+ else // (error & ATA_ERROR_REG_ABORT_BIT)
+ {
+ // The ABORT bit has the lowest precedence of all errors.
+ // As a result, it is at the bottom of the conditional
+ // statement.
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ }
+}
+
+/**
+ * @brief This method translates the supplied ATA payload data into the
+ * corresponding SCSI data. This is necessary for SCSI commands
+ * that have well-defined payload data associated with them (e.g.
+ * READ CAPACITY).
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[in] ata_io This parameter specifies the ATA payload
+ * buffer location and size to be translated.
+ * @param[out] scsi_output_data This parameter specifies the SCSI payload
+ * memory area into which the translator is to write.
+ *
+ * @return none
+ */
+static
+void sati_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ // Update the device capabilities in the odd/crazy event something changed.
+ sati_device_update_capabilities(
+ sequence->device, (ATA_IDENTIFY_DEVICE_DATA_T*) ata_input_data
+ );
+
+ // Look at the first byte to determine the SCSI command to translate.
+ switch (sequence->type)
+ {
+#if !defined(DISABLE_SATI_INQUIRY)
+ case SATI_SEQUENCE_INQUIRY_STANDARD:
+ sati_inquiry_standard_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER:
+ sati_inquiry_serial_number_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_INQUIRY_DEVICE_ID:
+ sati_inquiry_device_id_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE:
+ sati_inquiry_block_device_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_INQUIRY_ATA_INFORMATION:
+ sati_inquiry_ata_information_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+#endif // !defined(DISABLE_SATI_INQUIRY)
+
+#if !defined(DISABLE_SATI_READ_CAPACITY)
+ case SATI_SEQUENCE_READ_CAPACITY_10:
+ sati_read_capacity_10_translate_data(sequence, ata_input_data, scsi_io);
+ break;
+
+ case SATI_SEQUENCE_READ_CAPACITY_16:
+ sati_read_capacity_16_translate_data(sequence, ata_input_data, scsi_io);
+ break;
+#endif // !defined(DISABLE_SATI_READ_CAPACITY)
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+ case SATI_SEQUENCE_MODE_SENSE_6_CACHING:
+ sati_mode_sense_6_caching_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL:
+ sati_mode_sense_6_informational_excp_control_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR:
+ sati_mode_sense_6_read_write_error_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT:
+ sati_mode_sense_6_disconnect_reconnect_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_6_CONTROL:
+ sati_mode_sense_6_control_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES:
+ sati_mode_sense_6_all_pages_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION:
+ sati_mode_sense_6_power_condition_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION:
+ sati_mode_sense_10_power_condition_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_10_CACHING:
+ sati_mode_sense_10_caching_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL:
+ sati_mode_sense_10_informational_excp_control_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR:
+ sati_mode_sense_10_read_write_error_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT:
+ sati_mode_sense_10_disconnect_reconnect_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_10_CONTROL:
+ sati_mode_sense_10_control_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+
+ case SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES:
+ sati_mode_sense_10_all_pages_translate_data(
+ sequence, ata_input_data, scsi_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
+ default:
+ break;
+ }
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+SATI_STATUS sati_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ SATI_DEVICE_T * sati_device,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status = SATI_FAILURE;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ //No sense response has been set for the translation sequence yet
+ sequence->is_sense_response_set = FALSE;
+ // Default to no translation response required
+ sequence->is_translate_response_required = FALSE;
+ // Assign sati_device to sequence
+ sequence->device = sati_device;
+
+ /**
+ * Fail any I/O request with LUN != 0
+ */
+ if (sati_cb_get_lun(scsi_io) != 0)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
+ 0
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ /**
+ * SAT dictates:
+ * - the NACA bit in the control byte (last byte) must be 0
+ */
+ if ( (sati_get_cdb_byte(cdb, sati_cb_get_cdb_length(scsi_io) - 1)
+ & SCSI_CONTROL_BYTE_NACA_BIT_ENABLE))
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ /**
+ * Per SAT "Error and sense reporting" section. All subsequent IOs after
+ * a device fault should receive INTERNAL TARGET FAILURE sense data.
+ */
+ if (sati_device->state == SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_HARDWARE_ERROR,
+ SCSI_ASC_INTERNAL_TARGET_FAILURE,
+ SCSI_ASCQ_INTERNAL_TARGET_FAILURE
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+ {
+ sequence->command_specific_data.scratch = 0;
+ sequence->number_data_bytes_set = 0;
+ }
+
+
+#ifdef SATI_TRANSPORT_SUPPORTS_SATA
+ {
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+ sati_set_sata_command_flag(register_fis);
+ sati_set_sata_fis_type(register_fis, SATA_FIS_TYPE_REGH2D);
+ }
+#endif // SATI_TRANSPORT_SUPPORTS_SATA
+
+ // Look at the first byte to determine the SCSI command to translate.
+ switch (sati_get_cdb_byte(cdb, 0))
+ {
+#if !defined(DISABLE_SATI_REPORT_LUNS)
+ case SCSI_REPORT_LUNS:
+ status = sati_report_luns_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_REPORT_LUNS)
+
+#if !defined(DISABLE_SATI_INQUIRY)
+ case SCSI_INQUIRY:
+ status = sati_inquiry_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_INQUIRY)
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+ case SCSI_MODE_SENSE_6:
+ status = sati_mode_sense_6_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+
+ case SCSI_MODE_SENSE_10:
+ status = sati_mode_sense_10_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
+#if !defined(DISABLE_SATI_MODE_SELECT)
+ case SCSI_MODE_SELECT_6:
+ status = sati_mode_select_6_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+
+ case SCSI_MODE_SELECT_10:
+ status = sati_mode_select_10_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_MODE_SELECT)
+
+#if !defined(DISABLE_SATI_TEST_UNIT_READY)
+ case SCSI_TEST_UNIT_READY:
+ status = sati_test_unit_ready_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_TEST_UNIT_READY)
+
+#if !defined(DISABLE_SATI_READ_CAPACITY)
+ case SCSI_READ_CAPACITY_10:
+ status = sati_read_capacity_10_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+
+ case SCSI_SERVICE_ACTION_IN_16:
+ if ( (sati_get_cdb_byte(cdb, 1) & SCSI_SERVICE_ACTION_MASK)
+ == SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16)
+ status = sati_read_capacity_16_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ else
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+#endif // !defined(DISABLE_SATI_READ_CAPACITY)
+
+#if !defined(DISABLE_SATI_REQUEST_SENSE)
+ case SCSI_REQUEST_SENSE:
+ status = sati_request_sense_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_REQUEST_SENSE)
+
+ case SCSI_READ_6:
+ status = sati_read_6_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_READ_10:
+ status = sati_read_10_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_READ_12:
+ status = sati_read_12_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_READ_16:
+ status = sati_read_16_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_WRITE_6:
+ status = sati_write_6_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_WRITE_10:
+ status = sati_write_10_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_WRITE_12:
+ status = sati_write_12_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_WRITE_16:
+ status = sati_write_16_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+#if !defined(DISABLE_SATI_VERIFY)
+ case SCSI_VERIFY_10:
+ status = sati_verify_10_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_VERIFY_12:
+ status = sati_verify_12_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_VERIFY_16:
+ status = sati_verify_16_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif // !defined(DISABLE_SATI_VERIFY)
+
+#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \
+ && !defined(DISABLE_SATI_VERIFY) \
+ && !defined(DISABLE_SATI_WRITE)
+
+ case SCSI_WRITE_AND_VERIFY_10:
+ status = sati_write_and_verify_10_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_WRITE_AND_VERIFY_12:
+ status = sati_write_and_verify_12_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_WRITE_AND_VERIFY_16:
+ status = sati_write_and_verify_16_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+ // && !defined(DISABLE_SATI_VERIFY)
+ // && !defined(DISABLE_SATI_WRITE)
+
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+ case SCSI_REASSIGN_BLOCKS:
+ status = sati_reassign_blocks_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
+#if !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+ case SCSI_SYNCHRONIZE_CACHE_10:
+ case SCSI_SYNCHRONIZE_CACHE_16:
+ status = sati_synchronize_cache_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif // !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+
+#if !defined(DISABLE_SATI_START_STOP_UNIT)
+ case SCSI_START_STOP_UNIT:
+ status = sati_start_stop_unit_translate_command(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_START_STOP_UNIT)
+
+#if !defined(DISABLE_SATI_WRITE_LONG)
+ case SCSI_WRITE_LONG_10:
+ case SCSI_WRITE_LONG_16:
+ status = sati_write_long_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+
+#if !defined(DISABLE_SATI_LOG_SENSE)
+ case SCSI_LOG_SENSE:
+ status = sati_log_sense_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif // !defined(DISABLE_SATI_LOG_SENSE)
+
+ case SCSI_PERSISTENT_RESERVE_IN:
+ case SCSI_PERSISTENT_RESERVE_OUT:
+ //These commands are not supported by SATI
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
+ SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE
+ );
+ //returning status now to keep sense data set above
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+
+#if !defined(DISABLE_SATI_UNMAP)
+ case SCSI_UNMAP:
+ status = sati_unmap_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif // !defined(DISABLE_SATI_UNMAP)
+
+#if !defined(DISABLE_SATI_ATA_PASSTHROUGH)
+ case SCSI_ATA_PASSTHRU_12:
+ status = sati_passthrough_12_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+ case SCSI_ATA_PASSTHRU_16:
+ status = sati_passthrough_16_translate_command(sequence, scsi_io, ata_io);
+ break;
+
+#endif // !define(DISABLE_SATI_ATA_PASSTHRU)
+
+#if !defined(DISABLE_SATI_READ_BUFFER)
+ case SCSI_READ_BUFFER:
+ status = sati_read_buffer_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif //!defined(DISABLE_SATI_READ_BUFFER)
+
+#if !defined(DISABLE_SATI_WRITE_BUFFER)
+ case SCSI_WRITE_BUFFER:
+ status = sati_write_buffer_translate_command(sequence, scsi_io, ata_io);
+ break;
+#endif //!defined(DISABLE_SATI_WRITE_BUFFER)
+ default:
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+
+ if( (status == SATI_FAILURE_CHECK_RESPONSE_DATA) &&
+ !(sequence->is_sense_response_set) )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ }
+ return status;
+}
+
+// -----------------------------------------------------------------------------
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+SATI_STATUS sati_translate_task_management(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ SATI_DEVICE_T * sati_device,
+ void * scsi_task,
+ void * ata_io
+)
+{
+ SATI_STATUS status=SATI_FAILURE;
+ U8 task_function = sati_cb_get_task_function(scsi_task);
+
+ sequence->device = sati_device;
+
+ switch (task_function)
+ {
+ /**
+ * @todo We need to update the ABORT_TASK and ABORT_TASK_SET to be
+ * SAT compliant.
+ */
+ case SCSI_TASK_REQUEST_ABORT_TASK:
+ case SCSI_TASK_REQUEST_LOGICAL_UNIT_RESET:
+ status = sati_lun_reset_translate_command(sequence, scsi_task, ata_io);
+ break;
+
+ case SCSI_TASK_REQUEST_ABORT_TASK_SET:
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+ status = sati_abort_task_set_translate_command(sequence, scsi_task, ata_io);
+#else
+ status = SATI_FAILURE;
+#endif
+ break;
+ default:
+ status = SATI_FAILURE;
+ break;
+ }
+
+ return status;
+}
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+// -----------------------------------------------------------------------------
+#if !defined(DISABLE_SATI_INQUIRY) \
+ || !defined(DISABLE_SATI_READY_CAPACITY) \
+ || !defined(DISABLE_SATI_MODE_SENSE) \
+ || !defined(DISABLE_SATI_MODE_SELECT) \
+ || !defined(DISABLE_SATI_REASSIGN_BLOCKS) \
+ || !defined(DISABLE_SATI_START_STOP_UNIT) \
+ || !defined(DISABLE_SATI_REQUEST_SENSE) \
+ || !defined(DISABLE_SATI_WRITE_LONG) \
+ || !defined(DISABLE_SATI_LOG_SENSE) \
+ || !defined(DISABLE_SATI_UNMAP)
+
+static
+SATI_STATUS sati_check_data_io(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ return SATI_SEQUENCE_INCOMPLETE;
+ }
+ else if(sequence->number_data_bytes_set < sequence->allocation_length)
+ {
+ return SATI_COMPLETE_IO_DONE_EARLY;
+ }
+ else
+ {
+ return SATI_COMPLETE;
+ }
+}
+#endif // !defined(DISABLE_SATI_INQUIRY)
+ // || !defined(DISABLE_SATI_READY_CAPACITY)
+ // || !defined(DISABLE_SATI_MODE_SENSE)
+ // || !defined(DISABLE_SATI_MODE_SELECT)
+ // || !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+ // || !defined(DISABLE_SATI_START_STOP_UNIT)
+ // || !defined(DISABLE_SATI_REQUEST_SENSE)
+ // || !defined(DISABLE_SATI_WRITE_LONG)
+ // || !defined(DISABLE_SATI_LOG_SENSE)
+ // || !defined(DISABLE_SATI_UNMAP)
+// -----------------------------------------------------------------------------
+SATI_STATUS sati_translate_command_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status = SATI_COMPLETE;
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U8 ata_status;
+
+ /**
+ * If the device fault bit is set in the status register, then
+ * set the sense data and return.
+ */
+ ata_status = (U8) sati_get_ata_status(register_fis);
+ if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_HARDWARE_ERROR,
+ SCSI_ASC_INTERNAL_TARGET_FAILURE,
+ SCSI_ASCQ_INTERNAL_TARGET_FAILURE
+ );
+
+ sequence->device->state = SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED;
+
+ // Make sure that the terminate sequence is called to allow
+ // translation logic to perform any cleanup before the IO is completed.
+ sati_sequence_terminate(sequence,
+ scsi_io,
+ ata_io);
+
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // Look at the sequence type to determine the response translation method
+ // to invoke.
+ switch (sequence->type)
+ {
+#if !defined(DISABLE_SATI_TEST_UNIT_READY)
+ case SATI_SEQUENCE_TEST_UNIT_READY:
+ status = sati_test_unit_ready_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_TEST_UNIT_READY)
+
+#if !defined(DISABLE_SATI_INQUIRY) \
+ || !defined(DISABLE_SATI_READY_CAPACITY) \
+ || !defined(DISABLE_SATI_MODE_SENSE)
+
+ case SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG:
+
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ U8 error = (U8) sati_get_ata_error(register_fis);
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ sati_translate_error(sequence, scsi_io, error);
+ }
+ else
+ {
+ sati_inquiry_ata_information_finish_translation(
+ sequence,
+ scsi_io,
+ ata_io
+ );
+ status = sati_check_data_io(sequence);
+ }
+ break;
+
+ case SATI_SEQUENCE_INQUIRY_STANDARD:
+ case SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES:
+ case SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER:
+ case SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE:
+ case SATI_SEQUENCE_INQUIRY_ATA_INFORMATION:
+ case SATI_SEQUENCE_INQUIRY_DEVICE_ID:
+ case SATI_SEQUENCE_READ_CAPACITY_10:
+ case SATI_SEQUENCE_READ_CAPACITY_16:
+ case SATI_SEQUENCE_MODE_SENSE_6_CACHING:
+ case SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL:
+ case SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR:
+ case SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT:
+ case SATI_SEQUENCE_MODE_SENSE_6_CONTROL:
+ case SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION:
+ case SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES:
+ case SATI_SEQUENCE_MODE_SENSE_10_CACHING:
+ case SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL:
+ case SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR:
+ case SATI_SEQUENCE_MODE_SENSE_10_CONTROL:
+ case SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION:
+ case SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT:
+ case SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES:
+ // Did an error occur during the IO request?
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ U8 error = (U8) sati_get_ata_error(register_fis);
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ sati_translate_error(sequence, scsi_io, error);
+ }
+ else
+ {
+ void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+ if(ata_data == NULL)
+ {
+ status = SATI_FAILURE;
+ }
+ else
+ {
+ sati_translate_data(sequence, ata_data, scsi_io);
+ status = sati_check_data_io(sequence);
+ }
+ }
+ break;
+#endif // !defined(DISABLE_SATI_INQUIRY)
+ // && !defined(DISABLE_SATI_READY_CAPACITY)
+ // && !defined(DISABLE_SATI_MODE_SENSE)
+
+#if !defined(DISABLE_SATI_MODE_SELECT)
+ case SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING:
+
+ status = sati_mode_select_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+
+ case SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION:
+ case SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL:
+ // Did an error occur during the IO request?
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ U8 error = (U8) sati_get_ata_error(register_fis);
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ sati_translate_error(sequence, scsi_io, error);
+ }
+ else
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif // !defined(DISABLE_SATI_MODE_SELECT)
+
+#if !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+ case SATI_SEQUENCE_WRITE_AND_VERIFY:
+
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ U8 error = (U8) sati_get_ata_error(register_fis);
+ sati_translate_error(sequence, scsi_io, error);
+
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ status = sati_write_and_verify_translate_response(
+ sequence,
+ scsi_io,
+ ata_io
+ );
+ }
+ break;
+#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+
+ case SATI_SEQUENCE_READ_6:
+ case SATI_SEQUENCE_READ_10:
+ case SATI_SEQUENCE_READ_12:
+ case SATI_SEQUENCE_READ_16:
+ case SATI_SEQUENCE_WRITE_6:
+ case SATI_SEQUENCE_WRITE_10:
+ case SATI_SEQUENCE_WRITE_12:
+ case SATI_SEQUENCE_WRITE_16:
+ case SATI_SEQUENCE_VERIFY_10:
+ case SATI_SEQUENCE_VERIFY_12:
+ case SATI_SEQUENCE_VERIFY_16:
+ case SATI_SEQUENCE_SYNCHRONIZE_CACHE:
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ U8 error = (U8) sati_get_ata_error(register_fis);
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ sati_translate_error(sequence, scsi_io, error);
+
+ if(sequence->state == SATI_SEQUENCE_STATE_READ_ERROR )
+ {
+ sati_scsi_read_error_sense_construct(
+ sequence,
+ scsi_io,
+ ata_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_MEDIUM_ERROR,
+ SCSI_ASC_UNRECOVERED_READ_ERROR,
+ SCSI_ASCQ_UNRECOVERED_READ_ERROR
+ );
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ }
+ }
+ else
+ {
+ // We haven't satisified the transfer count from the original
+ // SCSI CDB. As a result, we need to re-issue the command
+ // with updated logical block address and transfer count.
+ if (sequence->command_specific_data.scratch)
+ {
+ /** @todo update the contents of the CDB directly? Should be
+ * done during previous command translation?
+ */
+ status = SATI_SEQUENCE_INCOMPLETE;
+ }
+ }
+ break;
+
+#if !defined(DISABLE_SATI_READ_BUFFER)
+ case SATI_SEQUENCE_READ_BUFFER:
+ status = sati_read_buffer_translate_response(
+ sequence, scsi_io, ata_io
+ );
+
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif //!defined(DISABLE_SATI_READ_BUFFER)
+
+#if !defined(DISABLE_SATI_WRITE_BUFFER)
+ case SATI_SEQUENCE_WRITE_BUFFER:
+ case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE:
+ status = sati_write_buffer_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif //!defined(DISABLE_SATI_WRITE_BUFFER)
+
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+ case SATI_SEQUENCE_REASSIGN_BLOCKS:
+ status = sati_reassign_blocks_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
+#if !defined(DISABLE_SATI_START_STOP_UNIT)
+ case SATI_SEQUENCE_START_STOP_UNIT:
+ status = sati_start_stop_unit_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif // !defined(DISABLE_SATI_START_STOP_UNIT)
+
+#if !defined(DISABLE_SATI_REQUEST_SENSE)
+ case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS:
+ case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE:
+ status = sati_request_sense_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif // !defined(DISABLE_SATI_REQUEST_SENSE)
+
+#if !defined(DISABLE_SATI_WRITE_LONG)
+ case SATI_SEQUENCE_WRITE_LONG:
+ status = sati_write_long_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+
+#if !defined(DISABLE_SATI_LOG_SENSE)
+ case SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE:
+ case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
+ case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
+ case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
+ status = sati_log_sense_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif // !defined(DISABLE_SATI_LOG_SENSE)
+
+#if !defined(DISABLE_SATI_UNMAP)
+ case SATI_SEQUENCE_UNMAP:
+ status = sati_unmap_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ if(status == SATI_COMPLETE)
+ {
+ status = sati_check_data_io(sequence);
+ }
+ break;
+#endif // !defined(DISABLE_SATI_UNMAP)
+
+#if !defined(DISABLE_SATI_ATA_PASSTHROUGH)
+ case SATI_SEQUENCE_ATA_PASSTHROUGH_12:
+ case SATI_SEQUENCE_ATA_PASSTHROUGH_16:
+ status = sati_passthrough_translate_response(
+ sequence, scsi_io, ata_io
+ );
+ break;
+#endif // !defined(DISABLE_SATI_ATA_PASSTHROUGH)
+
+ default:
+ status = SATI_FAILURE_INVALID_SEQUENCE_TYPE;
+ break;
+ }
+
+ return status;
+}
+
+// -----------------------------------------------------------------------------
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+SATI_STATUS sati_translate_task_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U8 ata_status;
+
+ /**
+ * If the device fault bit is set in the status register, then
+ * set the sense data and return.
+ */
+ ata_status = (U8) sati_get_ata_status(register_fis);
+ if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
+ {
+ sati_scsi_response_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_TASK_MGMT_FUNC_FAILED
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // Look at the sequence type to determine the response translation method
+ // to invoke.
+ switch (sequence->type)
+ {
+ case SATI_SEQUENCE_LUN_RESET:
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_response_data_construct(
+ sequence, scsi_io, SCSI_TASK_MGMT_FUNC_FAILED);
+ }
+ else
+ {
+ sati_scsi_response_data_construct(
+ sequence, scsi_io, SCSI_TASK_MGMT_FUNC_COMPLETE);
+ }
+
+ status = SATI_COMPLETE;
+ break;
+
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+ case SATI_SEQUENCE_ABORT_TASK_SET:
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_response_data_construct(
+ sequence, scsi_io, SCSI_TASK_MGMT_FUNC_FAILED);
+ }
+ else
+ {
+ void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+ if(ata_data == NULL)
+ {
+ status = SATI_FAILURE;
+ }
+ else
+ {
+ status = sati_abort_task_set_translate_data(
+ sequence,
+ ata_data,
+ scsi_io
+ );
+ }
+ }
+ break;
+#endif // !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+ default:
+ status = SATI_FAILURE_INVALID_SEQUENCE_TYPE;
+ break;
+ }
+
+ return status;
+}
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
+U32 sati_get_sat_compliance_version(
+ void
+)
+{
+ return 2; // Compliant with SAT-2.
+}
+
+U32 sati_get_sat_compliance_version_revision(
+ void
+)
+{
+ return 7; // Compliant with SAT-2 revision 7.
+}
+
+#endif // !defined(ENABLE_MINIMUM_MEMORY_MODE)
+
+U16 sati_get_number_data_bytes_set(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ return sequence->number_data_bytes_set;
+}
+
+void sati_sequence_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ sequence->state = SATI_SEQUENCE_STATE_INITIAL;
+}
+
+void sati_sequence_terminate(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ // Decode the sequence type to determine how to handle the termination
+ // of the the translation method.
+ switch (sequence->type)
+ {
+ case SATI_SEQUENCE_UNMAP:
+ sati_unmap_terminate(sequence,scsi_io,ata_io);
+ break;
+ }
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,271 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_H_
+#define _SATI_H_
+
+/**
+ * @file
+ * @brief This file contains all of the interface methods, macros, structures
+ * that can be utilized by a user to perform SCSI-to-ATA Translation.
+ * SATI adheres to the www.t10.org SAT specification.
+ *
+ * For specific compliance information please refer to:
+ * - sati_get_sat_compliance_version() and
+ * - sati_get_sat_compliance_version_revision()
+ *
+ * For situations where compliance is not observed, the SATI will
+ * return an error indication (most likely INVALID FIELD IN CDB sense).
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+/**
+ * @brief This method will be called by the core to indicate the start of a
+ * new translation sequence. Set up the initial sequence state.
+ *
+ * @return None
+ */
+void sati_sequence_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+/**
+ * @brief This method will be called by the core to request the current translation
+ * sequence be terminated.
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ * ATA register FIS into which the translator can write the
+ * resultant ATA command if translation is successful. This
+ * parameter is passed back to the user through the
+ * SATI_SATA_CALLBACKS when it is necessary to write fields
+ * in the ata_io.
+ *
+ * @return None
+ */
+void sati_sequence_terminate(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+/**
+ * @brief This method translates the supplied SCSI command into a
+ * corresponding ATA command.
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[in] sati_device This parameter specifies the remote device
+ * for which the translated request is destined.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ * ATA register FIS into which the translator can write the
+ * resultant ATA command if translation is successful. This
+ * parameter is passed back to the user through the
+ * SATI_SATA_CALLBACKS when it is necessary to write fields
+ * in the ata_io.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ SATI_DEVICE_T * sati_device,
+ void * scsi_io,
+ void * ata_io
+);
+
+/**
+ * @brief This method translates the supplied SCSI task management request
+ * into a corresponding ATA command/control FIS.
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[in] sati_device This parameter specifies the remote device
+ * for which the translated request is destined.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ * ATA register FIS into which the translator can write the
+ * resultant ATA command if translation is successful. This
+ * parameter is passed back to the user through the
+ * SATI_SATA_CALLBACKS when it is necessary to write fields
+ * in the ata_io.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_task_management(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ SATI_DEVICE_T * sati_device,
+ void * scsi_task,
+ void * ata_io
+);
+
+/**
+ * @brief This method translates the supplied ATA response into the
+ * corresponding SCSI command response.
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ * ATA IO request (e.g. register FIS, PIO Setup etc.) from which
+ * the translator can read the received ATA status and error
+ * fields.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_command_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+/**
+ * @brief This method translates the supplied ATA response into the
+ * corresponding SCSI task response.
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[out] ata_io This parameter specifies the location of the
+ * ATA IO request (e.g. register FIS, PIO Setup etc.) from which
+ * the translator can read the received ATA status and error
+ * fields.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_translate_task_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+/**
+ * @brief This method simply returns the SAT major compliance version number
+ * for which the implementation is compliant.
+ *
+ * @return Return the specification identifier with which this translator
+ * is compliant.
+ */
+U32 sati_get_sat_compliance_version(
+ void
+);
+
+/**
+ * @brief This method simply returns the SAT version revision identifier
+ * for which the implementation is compliant.
+ *
+ * @return Return the specification revision identifier with which this
+ * translator is compliant.
+ */
+U32 sati_get_sat_compliance_version_revision(
+ void
+);
+
+/**
+* @brief This method returns the number of data bytes written
+* by the translation sequence.
+*
+* @param[in] sequence This parameter specifies the sequence data
+* associated with the translation.
+*
+* @return Return the U16 number_data_bytes_set in the
+* SATI_TRANSLATOR_SEQUENCE.
+*/
+U16 sati_get_number_data_bytes_set(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_translate_error(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 error
+);
+
+#endif // _SATI_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_abort_task_set.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_abort_task_set.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,177 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations required to
+ * translate the SCSI abort task set command.
+ */
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+#include <dev/isci/scil/sati_abort_task_set.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+/**
+ * @brief This method will translate the abort task set SCSI task request into an
+ * ATA READ LOG EXT command. For more information on the parameters
+ * passed to this method, please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ */
+SATI_STATUS sati_abort_task_set_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis;
+
+ //ATA Read Log Ext with log address set to 0x10
+ sati_ata_read_log_ext_construct(
+ ata_io,
+ sequence,
+ ATA_LOG_PAGE_NCQ_ERROR,
+ sizeof(ATA_NCQ_COMMAND_ERROR_LOG_T)
+ );
+
+ register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+ sati_set_sata_command_flag(register_fis);
+
+ sequence->type = SATI_SEQUENCE_ABORT_TASK_SET;
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+
+ return SATI_SUCCESS;
+}
+
+SATI_STATUS sati_abort_task_set_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_task
+)
+{
+ ATA_NCQ_COMMAND_ERROR_LOG_T * log =
+ (ATA_NCQ_COMMAND_ERROR_LOG_T *)ata_input_data;
+ U8 tag_index;
+
+ sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
+
+ for (tag_index = 0; tag_index < 32; tag_index++)
+ {
+ void * matching_command;
+ SCI_STATUS completion_status;
+ sati_cb_device_get_request_by_ncq_tag(
+ scsi_task,
+ tag_index,
+ matching_command
+ );
+
+ if (matching_command != NULL)
+ {
+ if (
+ (log->ncq_tag == tag_index) &&
+ (log->nq == 0) // nq==1 means a non-queued command
+ // caused this failure
+ )
+ {
+ sati_translate_error(sequence, matching_command, log->error);
+ completion_status = SCI_FAILURE_IO_RESPONSE_VALID;
+
+ if(sequence->state == SATI_SEQUENCE_STATE_READ_ERROR)
+ {
+ //Uncorrectable read error, return additional sense data
+ sati_scsi_read_ncq_error_sense_construct(
+ sequence,
+ matching_command,
+ ata_input_data,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_MEDIUM_ERROR,
+ SCSI_ASC_UNRECOVERED_READ_ERROR,
+ SCSI_ASCQ_UNRECOVERED_READ_ERROR
+ );
+ }
+ }
+ else
+ {
+ completion_status = SCI_FAILURE_IO_TERMINATED;
+ }
+
+ sati_cb_io_request_complete(matching_command, completion_status);
+ }
+ }
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+
+ return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_abort_task_set.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_abort_task_set.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,83 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_ABORT_TASK_SET_H_
+#define _SATI_ABORT_TASK_SET_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to translate the
+ * SCSI abort task set task request as well as translate response
+ * for the task request.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#if !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+SATI_STATUS sati_abort_task_set_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_task,
+ void * ata_io
+);
+
+SATI_STATUS sati_abort_task_set_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_task
+);
+
+#endif // !defined(DISABLE_SATI_ABORT_TASK_SET)
+
+#endif // _SATI_ABORT_TASK_SET_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_atapi.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_atapi.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,257 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the method implementations that
+ * can be utilized by a user to perform SCSI-to-ATA Translation.
+ * SATI adheres to the www.t10.org SAT specification.
+ *
+ * For situations where compliance is not observed, the SATI will
+ * return an error indication (most likely INVALID FIELD IN CDB sense data).
+ */
+
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_atapi.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/sati_report_luns.h>
+
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+SATI_STATUS sati_atapi_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ SATI_DEVICE_T * sati_device,
+ void * scsi_io,
+ void * atapi_io
+)
+{
+ SATI_STATUS status;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ SATA_FIS_REG_H2D_T * register_fis =
+ (SATA_FIS_REG_H2D_T *)sati_cb_get_h2d_register_fis_address(atapi_io);
+
+ U8 io_direction = SATI_DATA_DIRECTION_IN;
+
+ //No sense response has been set for the translation sequence yet
+ sequence->is_sense_response_set = FALSE;
+ // Default to no translation response required
+ sequence->is_translate_response_required = FALSE;
+
+ sequence->number_data_bytes_set = 0;
+ sequence->device = sati_device;
+ sequence->command_specific_data.scratch = 0;
+
+ sati_cb_get_data_direction(scsi_io, &io_direction);
+
+ //set sat protocol.
+ if (io_direction == SATI_DATA_DIRECTION_NONE)
+ sequence->protocol = SAT_PROTOCOL_PACKET_NON_DATA;
+ else if (io_direction == SATI_DATA_DIRECTION_IN)
+ sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;
+ else if (io_direction == SATI_DATA_DIRECTION_OUT)
+ sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_OUT;
+
+ // We don't send Report Luns command out.
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_REPORT_LUNS)
+ {
+ status = sati_report_luns_translate_command(
+ sequence, scsi_io, atapi_io
+ );
+ }
+ else if (sati_cb_get_lun(scsi_io) != 0)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_LOGICAL_UNIT_NOT_SUPPORTED,
+ 0
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ { //Request Sense command is required.
+ U8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH] =
+ {0x3, 0x0, 0x0, 0x0, 0x12, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+ //set the sequence->protocol to DATA_IN anyway;
+ sequence->protocol = SAT_PROTOCOL_PACKET_DMA_DATA_IN;
+
+ //set the cdb for Request Sense using command_specific_data field.
+ memcpy(sequence->command_specific_data.sati_atapi_data.request_sense_cdb,
+ request_sense_cdb,
+ SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH
+ );
+ }
+
+ //build Packet Fis for any other command translation.
+ register_fis->command = ATA_PACKET;
+ register_fis->features |= ATA_PACKET_FEATURE_DMA;
+
+ register_fis->fis_type = SATA_FIS_TYPE_REGH2D;
+ register_fis->command_flag = 1;
+
+ status = SATI_SUCCESS;
+ }
+
+ return status;
+}
+
+
+SATI_STATUS sati_atapi_translate_command_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * atapi_io
+)
+{
+ SATI_STATUS status = SATI_COMPLETE;
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(atapi_io);
+ U8 ata_status;
+
+ /**
+ * If the device fault bit is set in the status register, then
+ * set the sense data and return.
+ */
+ ata_status = (U8) sati_get_ata_status(register_fis);
+ if (ata_status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_HARDWARE_ERROR,
+ SCSI_ASC_INTERNAL_TARGET_FAILURE,
+ SCSI_ASCQ_INTERNAL_TARGET_FAILURE
+ );
+
+ sequence->device->state = SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED;
+
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ //reset the register_fis.
+ memset(register_fis, 0, sizeof(SATA_FIS_REG_D2H_T));
+
+ //Internal Request Sense command is needed.
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ return SATI_SEQUENCE_INCOMPLETE;
+ }
+
+ return status;
+}
+
+void sati_atapi_translate_request_sense_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * atapi_io
+)
+{
+ //sense data is already in place.
+ SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
+ sati_cb_get_response_iu_address(scsi_io);
+
+ sati_scsi_common_response_iu_construct(
+ rsp_iu,
+ SCSI_STATUS_CHECK_CONDITION,
+ sati_scsi_get_sense_data_length(sequence, scsi_io),
+ SCSI_RESPONSE_DATA_PRES_SENSE_DATA
+ );
+
+ sequence->is_sense_response_set = TRUE;
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+}
+
+
+U32 sati_atapi_translate_number_of_bytes_transferred(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * atapi_io
+)
+{
+ U8* cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 response_data;
+ U32 data_length = 0;
+
+ switch(cdb[0])
+ {
+ case SCSI_MODE_SENSE_10:
+ sati_cb_get_data_byte(scsi_io, 1, &response_data);
+ data_length = response_data+2;
+ break;
+
+ case 0x51: //READ DISC INFORMATION
+ sati_cb_get_data_byte(scsi_io, 1, &response_data);
+ data_length = response_data+2;
+ break;
+
+ default:
+ break;
+ }
+
+ return data_length;
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_atapi.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_atapi.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,177 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_ATAPI_H_
+#define _SATI_ATAPI_H_
+
+/**
+ * @file
+ * @brief This file contains all of the interface methods, macros, structures
+ * that can be utilized by a user to perform SCSI-to-ATA PACKET IO
+ * Translation.
+ */
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+/**
+ * @brief This method translates the supplied SCSI command into a
+ * corresponding ATA packet protocol command.
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[in] sati_device This parameter specifies the remote device
+ * for which the translated request is destined.
+ * @param[in,out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[out] atapi_io This parameter specifies the location of the
+ * ATA Packet FIS into which the translator can write the resultant
+ * ATA command if translation is successful. This parameter is
+ * passed back to the user through the SATI_SATA_CALLBACKS when it
+ * is necessary to write fields in the ata_io.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_atapi_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ SATI_DEVICE_T * sati_device,
+ void * scsi_io,
+ void * atapi_io
+);
+
+
+/**
+ * @brief This method translates the supplied ATA packet IO response into the
+ * corresponding SCSI command response.
+ *
+ * @param[out] sequence This parameter specifies the sequence
+ * data associated with the translation and will be updated
+ * according to the command response.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[in] atapi_io This parameter specifies the location of the
+ * ATAPI IO request (e.g. register FIS, PIO Setup etc.) from which
+ * the translator can read the received ATA status and error
+ * fields.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+SATI_STATUS sati_atapi_translate_command_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * atapi_io
+);
+
+
+/**
+ * @brief This method translates the internal Request Sense command response
+ * and set the sense data for the previous failed SCSI command.
+ *
+ * @param[out] sequence This parameter specifies the sequence
+ * data associated with the translation and to be updated to
+ * final state.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[in] atapi_io This parameter specifies the location of the
+ * ATAPI IO request (e.g. register FIS, PIO Setup etc.) from which
+ * the translator can read the received ATA status and error
+ * fields.
+ *
+ * @return None.
+ */
+void sati_atapi_translate_request_sense_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * atapi_io
+);
+
+
+/**
+ * @brief This method retrieve ATA packet IO actual transferred data length.
+ *
+ * @param[in] sequence This parameter specifies the sequence
+ * data associated with the translation.
+ * @param[out] scsi_io This parameter specifies the user's SCSI IO request
+ * object. SATI expects that the user can access the SCSI CDB,
+ * response, and data from this pointer. For example, if there
+ * is a failure in translation resulting in sense data, then
+ * SATI will call sati_cb_set_status() and pass the scsi_io
+ * pointer as a parameter.
+ * @param[out] atapi_io This parameter specifies the location of the
+ * ATAPI IO request (e.g. register FIS, PIO Setup etc.) from which
+ * the translator can read the received ATA status and error
+ * fields.
+ *
+ * @return Actual data transfer length.
+ */
+U32 sati_atapi_translate_number_of_bytes_transferred(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * atapi_io
+);
+#endif
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_callbacks.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_callbacks.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,481 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_CALLBACKS_H_
+#define _SATI_CALLBACKS_H_
+
+/**
+ * @file
+ * @brief This file contains the default callback bindings for SATI. These
+ * must be overridden by the SATI user to ensure successful operation.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/intel_sas.h>
+
+#ifdef SATI_DEFAULT_DECLARATION
+
+/**
+ * @brief This callback method asks the user to provide the address for
+ * the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scsi_io This parameter points to the user's IO request object
+ * It is a cookie that allows the user to provide the necessary
+ * information for this callback.
+ *
+ * @return This method returns the virtual address of the CDB.
+ */
+void * sati_cb_get_cdb_address(
+ void * scsi_io
+);
+
+/**
+ * @brief This callback method asks the user to provide the length of
+ * the command descriptor block (CDB) associated with this IO request.
+ *
+ * @param[in] scsi_io This parameter points to the user's IO request object.
+ * It is a cookie that allows the user to provide the necessary
+ * information for this callback.
+ *
+ * @return This method returns the length of the CDB.
+ */
+U32 sati_cb_get_cdb_length(
+ void * scsi_io
+);
+
+/**
+ * @brief This callback method asks the user to provide the data transfer
+ * direction of this IO request.
+ *
+ * @param[in] scsi_io This parameter points to the user's IO request object.
+ * It is a cookie that allows the user to provide the necessary
+ * information for this callback.
+ * @param[in] io_direction to return
+ * @return This method returns the length of the CDB.
+ */
+void sati_cb_get_data_direction(
+ void * scsi_io,
+ U8 * io_direction
+);
+
+/**
+ * @brief This callback method sets a value into the data buffer associated
+ * with the supplied user SCSI IO request at the supplied byte offset.
+ *
+ * @note SATI does not manage the user scatter-gather-list. As a result,
+ * the user must ensure that data is written according to the SGL.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to set the data buffer byte.
+ * @param[in] byte_offset This parameter specifies the offset into the
+ * data buffer at which to set the value.
+ * @param[in] value This parameter specifies the new value to be set into
+ * the data buffer.
+ *
+ * @return none
+ */
+void sati_cb_set_data_byte(
+ void * scsi_io,
+ U32 byte_offset,
+ U8 value
+);
+
+/**
+ * @brief This callback method gets a value from the data buffer associated
+ * with the supplied user SCSI IO request at the supplied byte offset.
+ *
+ * @note SATI does not manage the user scatter-gather-list. As a result,
+ * the user must ensure that data is written according to the SGL.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to get the data buffer byte.
+ * @param[in] byte_offset This parameter specifies the offset into the
+ * data buffer at which to get the value.
+ * @param[in] value This parameter specifies the new value to be get into
+ * the data buffer.
+ *
+ * @return none
+ */
+void sati_cb_get_data_byte(
+ void * scsi_io,
+ U32 byte_offset,
+ U8 * value
+);
+
+/**
+ * @brief This callback method gets the the task type for the SCSI task
+ * request.
+ *
+ * @param[in] scsi_task This parameter specifies the user's SCSI Task request.
+ * It is a cookie that allows the user to provide the necessary
+ * information for this callback.
+ *
+ * @return This method returns one of the enumeration values for
+ * SCSI_TASK_MGMT_REQUEST_CODES
+ */
+U8 sati_cb_get_task_function(
+ void * scsi_task
+);
+
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+/**
+ * @brief This callback method retrieves the address of the user's SSP
+ * response IU buffer.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to retreive the location of the response buffer to
+ * be written.
+ *
+ * @return This method returns the address of the response data buffer.
+ */
+void * sati_cb_get_response_iu_address(
+ void * scsi_io
+);
+
+#else // SATI_TRANSPORT_SUPPORTS_SAS
+
+/**
+ * @brief This callback method retrieves the address of the user's sense data
+ * buffer.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to retreive the location of the sense buffer to
+ * be written.
+ *
+ * @return This method returns the address of the sense data buffer.
+ */
+U8* sati_cb_get_sense_data_address(
+ void * scsi_io
+);
+
+/**
+ * @brief This callback method retrieves the length of the user's sense data
+ * buffer.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to retreive the location of the sense buffer to
+ * be written.
+ *
+ * @return This method returns the length of the sense data buffer.
+ */
+U32 sati_cb_get_sense_data_length(
+ void * scsi_io
+);
+
+/**
+ * @brief This callback method sets the SCSI status to be associated with
+ * the supplied user's SCSI IO request.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to set the SCSI status.
+ * @param[in] status This parameter specifies the SCSI status to be
+ * associated with the supplied user's SCSI IO request.
+ *
+ * @return none
+ */
+void sati_cb_set_scsi_status(
+ void * scsi_io,
+ U8 status
+);
+
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+
+/**
+ * @brief This method retrieves the ATA task file (register FIS) relating to
+ * the host to device command values.
+ *
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ * from which to retrieve the h2d register FIS address.
+ *
+ * @return This method returns the address for the host to device register
+ * FIS.
+ */
+U8 * sati_cb_get_h2d_register_fis_address(
+ void * ata_io
+);
+
+/**
+ * @brief This method retrieves the ATA task file (register FIS) relating to
+ * the device to host reponse values.
+ *
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ * from which to retrieve the d2h register FIS address.
+ *
+ * @return This method returns the address for the device to host register
+ * FIS.
+ */
+U8 * sati_cb_get_d2h_register_fis_address(
+ void * ata_io
+);
+
+/**
+ * @brief This method retrieves the address where the ATA data received
+ * from the device is stored.
+ *
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ * from which to retrieve the received data address.
+ *
+ * @return This method returns the address for the data received from
+ * the remote device.
+ */
+void * sati_cb_get_ata_data_address(
+ void * ata_io
+);
+
+/**
+ * @brief This method allocates a DMA buffer
+ * that can be utilized for small (<=4K) DMA sequences.
+ * This is utilized to translate SCSI UNMAP requests.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to set the SCSI status.
+ * @param[in] length in bytes of the buffer to be allocated
+ * @param[in] virtual address of the allocated DMA buffer.
+ * @param[in] low 32 bits of the physical DMA address.
+ * @param[in] high 32 bits of the physical DMA address.
+ *
+ * @return This method returns the virtual and physical address
+ * of the allocated DMA buffer.
+ */
+void sati_cb_allocate_dma_buffer(
+ void * scsi_io,
+ U32 length,
+ void ** virt_address,
+ U32 * phys_address_low,
+ U32 * phys_address_high
+);
+
+/**
+ * @brief This method frees a previously allocated DMA buffer
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to set the SCSI status.
+ * @param[in] address - write buffer address being freed
+ *
+ * @return This method returns the address for the data received from
+ * the remote device.
+ */
+void sati_cb_free_dma_buffer(
+ void * scsi_io,
+ void * virt_address
+);
+
+/**
+ * @brief This method retrieves a pointer to the next scatter gather
+ * list element.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * from which to retrieve the scatter gather list.
+ * @param[in] ata_io This parameter specifies the user's ATA IO request
+ * from which to retrieve the scatter gather list.
+ * @param[in] current_sge This parameter specifies the current SG element
+ * being pointed to. If retrieving the first element,
+ * then this value should be NULL.
+ * @param[in] next_sge This parameter is the returned SGL element
+ * based on current_sge.
+ *
+ * @return This method returns a pointer to the scatter gather element.
+ */
+void sati_cb_sgl_next_sge(
+ void * scsi_io,
+ void * ata_io,
+ void * current_sge,
+ void ** next_sge
+);
+
+/**
+ * @brief This method will set the next scatter-gather elements address
+ * low field.
+ *
+ * @param[in] current_sge This parameter specifies the current SG element
+ * being pointed to.
+ * @param[in] address_low This parameter specifies the lower 32-bits
+ * of address to be programmed into the SG element.
+ * @param[in] address_high This parameter specifies the upper 32-bits
+ * of address to be programmed into the SG element.
+ * @param[in] length This parameter specifies the number of bytes
+ * to be programmed into the SG element.
+ *
+ * @return none
+ */
+void sati_cb_sge_write(
+ void * current_sge,
+ U32 phys_address_low,
+ U32 phys_address_high,
+ U32 byte_length
+);
+
+/**
+ * @brief This method will check to see if the translation requires
+ * a translation response callback. Some translations need to be alerted on all
+ * failures so sequence cleanup can be completed for halting the translation.
+ *
+ * @param[in] the current SCIC request under going translation.
+ *
+ * @return TRUE A response callback will be required to complete this translation sequence.
+ */
+BOOL sati_cb_do_translate_response(
+ void * request
+);
+
+/**
+ * @brief This method retrieves the SAS address for the device associated
+ * with the supplied SCSI IO request. This method assumes that the
+ * associated device is contained in a SAS Domain.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO request
+ * for which to retreive the SAS address of the device.
+ * @param[out] sas_address This parameter specifies the SAS address memory
+ * to be contain the retrieved value.
+ *
+ * @return none
+ */
+void sati_cb_device_get_sas_address(
+ void * scsi_io,
+ SCI_SAS_ADDRESS_T * sas_address
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied
+ * error information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is an error from the core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_error(
+ void * logger_object,
+ U32 log_object_mask,
+ char * log_message,
+ ...
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied warning
+ * information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a warning from the core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_warning(
+ void * logger_object,
+ U32 log_object_mask,
+ char * log_message,
+ ...
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied debug
+ * information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a debug message from the core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_info(
+ void * logger_object,
+ U32 log_object_mask,
+ char * log_message,
+ ...
+);
+
+/**
+ * @brief In this method the user is expected to log the supplied function
+ * trace information. The user must be capable of handling variable
+ * length argument lists and should consider prepending the fact
+ * that this is a function trace (i.e. entry/exit) message from the
+ * core.
+ *
+ * @param[in] logger_object This parameter specifies the logger object
+ * associated with this message.
+ * @param[in] log_object_mask This parameter specifies the log objects
+ * for which this message is being generated.
+ * @param[in] log_message This parameter specifies the message to be logged.
+ *
+ * @return none
+ */
+void sati_cb_logger_log_trace(
+ void * logger_object,
+ U32 log_object_mask,
+ char * log_message,
+ ...
+);
+
+#include <dev/isci/scil/sati_callbacks_implementation.h>
+
+#else // SATI_DEFAULT_DECLARATION
+
+#include <dev/isci/scil/scif_sas_sati_binding.h>
+#endif // SATI_DEFAULT_DECLARATION
+
+#endif // _SATI_CALLBACKS_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_design.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_design.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,169 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_DESIGN_H_
+#define _SATI_DESIGN_H_
+
+/**
+ at page sati_design_page SATI High Level Design
+
+<b>Authors:</b>
+- Nathan Marushak
+
+ at section scif_sas_scope_and_audience Scope and Audience
+
+This document provides design information relating to the SCSI to ATA
+Translation Implementation (SATI). Driver developers are the primary
+audience for this document. The reader is expected to have an understanding
+of SCSI (Simple Computer Storage Interface), ATA (Advanced Technology
+Attachment), and SAT (SCSI-to-ATA Translation).
+
+Please refer to www.t10.org for specifications relating to SCSI and SAT.
+Please refer to www.t13.org for specifications relating to ATA.
+
+ at section overview Overview
+
+SATI provides environment agnostic functionality for translating SCSI
+commands, data, and responses into ATA commands, data, and responses. As
+a result, in some instances the user must fill out callbacks to set data.
+This ensures that user isn't forced to have to copy the data an additional
+time due to memory access restrictions.
+
+SATI complies with the t10 SAT specification where possible. In cases where
+there are variances the design and implementation will make note.
+Additionally, for parameters, pages, functionality, or commands for which
+SATI is unable to translate, SATI will return sense data indicating
+INVALID FIELD IN CDB.
+
+SATI has two primary entry points from which the user can enter:
+- sati_translate_command()
+- sati_translate_response() (this method performs data translation).
+
+Additionally, SATI provides a means through which the user can query to
+determine the t10 specification revision with which SATI is compliant. For
+more information please refer to:
+- sati_get_sat_compliance_version()
+- sati_get_sat_compliance_version_revision()
+
+ at section sati_definitions Definitions
+
+- scsi_io: The SCSI IO is considered to be the user's SCSI IO request object
+(e.g. the windows driver IO request object and SRB). It is passed back to
+the user via callback methods to retrieve required SCSI information (e.g. CDB,
+response IU address, etc.). The SCSI IO is just a cookie and can represent
+any value the caller desires, but the user must be able to utilize this value
+when it is passed back through callback methods during translation.
+- ata_io: The ATA IO is considered to be the user's ATA IO request object. If
+you are utilizing the SCI Framework, then the SCI Framework is the ATA IO.
+The ATA IO is just a cookie and can represent any value the caller desires,
+but the user must be able to utilize this value when it is passed back
+through callback methods during translation.
+
+ at section sati_use_cases Use Cases
+
+The SCSI Primary Command (SPC) set is comprised of commands that are valid
+for all device types defined in SCSI. Some of these commands have
+sub-commands or parameter data defined in another specification (e.g. SBC, SAT).
+These separate sub-commands or parameter data are captured in the SPC use
+case diagram for simplicity.
+
+ at note
+- For simplicify the association between the actor and the use cases
+has not been drawn, but is assumed.
+- The use cases in green indicate the use case has been implemented in
+ source.
+
+ at image html Use_Case_Diagram__SATI__SATI_-_SPC.jpg "SCSI Primary Command Translation Use Cases"
+
+The SCSI Block Command (SBC) set is comprised of commands that are valid for
+block devices (e.g. disks).
+
+ at image html Use_Case_Diagram__SATI__SATI_-_SBC.jpg "SCSI Block Command Translation Use Cases"
+
+The SCSI-to-ATA Translation (SAT) specification defines a few of it's own
+commands, parameter data, and log pages. This use case diagram, however, only
+captures the SAT specific commands being translated.
+
+ at image html Use_Case_Diagram__SATI__SATI_-_SAT_Specific.jpg "SCSI-to-ATA Translation Specific Use Cases"
+
+ at section sati_class_hierarchy Class Hierarchy
+
+ at image html Class_Diagram__SATI__Class_Diagram.jpg "SATI Class Diagram"
+
+ at section sati_sequences Sequence Diagrams
+
+ at note These sequence diagrams are currently a little out of date. An
+ update is required.
+
+This sequence diagram simply depicts the high-level translation sequence to
+be followed for command translations.
+
+ at image html Sequence_Diagram__General_Cmd_Translation_Sequence__General_Cmd_Translation_Sequence.jpg "General Command Translation Sequence"
+
+This sequence diagram simply depicts the high-level translation sequence to
+be followed for reponse translations.
+
+ at image html Sequence_Diagram__General_Rsp_Translation_Sequence__General_Rsp_Translation_Sequence.jpg "General Response Translation Sequence"
+
+This sequence diagram simply depicts the high-level translation sequence to
+be followed for data translations. Some SCSI commands such as READ CAPACITY,
+INQUIRY, etc. have payload data associated with them. As a result, it is
+necessary for the ATA payload data to be translated to meet the expected SCSI
+output.
+
+ at image html Sequence_Diagram__General_Data_Translation_Sequence__General_Data_Translation_Sequence.jpg "General Data Translation Sequence"
+
+*/
+
+#endif // _SATI_DESIGN_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_device.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_device.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,245 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the defintions for the SATI remote
+ * device object. Some translations require information to be
+ * remembered on a per device basis. This information is stored
+ * in the object defined in this file.
+ */
+
+#include <dev/isci/scil/sati_device.h>
+#include <dev/isci/scil/sci_util.h> // Move this file.
+#include <dev/isci/scil/sati_unmap.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method simply initializes the data members in the device
+ * object to their appropriate values.
+ *
+ * @param[in] device This parameter specifies the device for which to
+ * initialize the data members.
+ * @param[in] is_ncq_enabled This parameter specifies if NCQ is to be
+ * utilized for this particular SATI device.
+ * @param[in] max_ncq_depth This parameter specifies the maximum desired
+ * NCQ depth. Once this value is set it can never be increased.
+ * @param[in] ignore_fua This parameter specifies FUA is to be ignored and not
+ * sent to the end device. Some OS (Windows) has quirky behaviors with FUA
+ * and recommend driver developers ignore the bit.
+ *
+ * @return none
+ */
+void sati_device_construct(
+ SATI_DEVICE_T * device,
+ BOOL is_ncq_enabled,
+ U8 max_ncq_depth,
+ BOOL ignore_fua
+)
+{
+ device->state = SATI_DEVICE_STATE_OPERATIONAL;
+ device->capabilities = 0;
+ device->descriptor_sense_enable = SCSI_MODE_PAGE_CONTROL_D_SENSE_DISABLE;
+
+ // The user requested that NCQ be utilized if it is supported by
+ // the device.
+ if (is_ncq_enabled == TRUE)
+ device->capabilities |= SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE;
+
+ device->ncq_depth = max_ncq_depth;
+
+ // The user requested that FUA is ignored (windows performance issue)
+ if (ignore_fua == TRUE)
+ device->capabilities |= SATI_DEVICE_CAP_IGNORE_FUA;
+
+}
+
+/**
+ * @brief This method will update the SATI_DEVICE capabilities based on
+ * the supplied ATA_IDENTIFY_DEVICE_DATA.
+ *
+ * @param[in] device This parameter specifies the device for which to update
+ * the supported capabilities.
+ * @param[in] identify This parameter specifies the ata identify device
+ * information from which to extract the capabilities of the
+ * device.
+ *
+ * @return none
+ */
+void sati_device_update_capabilities(
+ SATI_DEVICE_T * device,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify
+)
+{
+ U16 capabilities = 0;
+
+ if (identify->capabilities1 & ATA_IDENTIFY_CAPABILITIES1_NORMAL_DMA_ENABLE)
+ capabilities |= SATI_DEVICE_CAP_UDMA_ENABLE;
+
+ if (identify->command_set_supported1
+ & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
+ {
+ capabilities |= SATI_DEVICE_CAP_48BIT_ENABLE;
+ }
+
+ if (identify->command_set_supported0
+ & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
+ {
+ capabilities |= SATI_DEVICE_CAP_SMART_SUPPORT;
+ }
+
+ if (identify->command_set_enabled0
+ & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
+ {
+ capabilities |= SATI_DEVICE_CAP_SMART_ENABLE;
+ }
+
+ // Save the NCQ related capabilities information.
+ if (identify->serial_ata_capabilities
+ & ATA_IDENTIFY_SATA_CAPABILITIES_NCQ_ENABLE)
+ {
+ if (device->capabilities & SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE)
+ {
+ capabilities |= SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE;
+ capabilities |= SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE;
+ capabilities |= SATI_DEVICE_CAP_DMA_FUA_ENABLE;
+ device->ncq_depth = MIN(
+ device->ncq_depth,
+ (U8) (identify->queue_depth
+ & ATA_IDENTIFY_NCQ_QUEUE_DEPTH_ENABLE) + 1
+ );
+ }
+ }
+
+ // if the user requested that FUA is ignored; transfer it so we don't lose on update.
+ if (device->capabilities & SATI_DEVICE_CAP_IGNORE_FUA)
+ capabilities |= SATI_DEVICE_CAP_IGNORE_FUA;
+
+ if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE)
+ capabilities |= SATI_DEVICE_CAP_REMOVABLE_MEDIA;
+
+ if(identify->command_set_supported2 & ATA_IDENTIFY_WRITE_UNCORRECTABLE_SUPPORT )
+ {
+ capabilities |= SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE;
+ }
+
+ if(identify->physical_logical_sector_info &
+ ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE)
+ {
+ capabilities |= SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR;
+ }
+
+ if(identify->command_set_supported_extention &
+ ATA_IDENTIFY_COMMAND_SET_SMART_SELF_TEST_SUPPORTED)
+ {
+ capabilities |= SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT;
+ }
+
+ if (identify->nominal_media_rotation_rate == 1)
+ {
+ capabilities |= SATI_DEVICE_CAP_SSD;
+ }
+
+ // Save off the logical block size reported by the drive
+ // See if Word 106 is valid and reports a logical sector size
+ if ((identify->physical_logical_sector_info & 0x5000) == 0x5000)
+ {
+ device->logical_block_size = (identify->words_per_logical_sector[3] << 24) |
+ (identify->words_per_logical_sector[2] << 16) |
+ (identify->words_per_logical_sector[1] << 8) |
+ (identify->words_per_logical_sector[0]);
+ }
+ else
+ {
+ device->logical_block_size = 512;
+ }
+
+ // Determine DSM TRIM capabilities
+ // Defend against SSDs which report TRIM support, but set
+ // max_lba_range_entry_blocks to zero, by disabling TRIM for
+ // those SSDs.
+ if (
+ (identify->data_set_management & ATA_IDENTIFY_COMMAND_SET_DSM_TRIM_SUPPORTED)
+ && (identify->max_lba_range_entry_blocks > 0)
+ )
+ {
+ capabilities |= SATI_DEVICE_CAP_DSM_TRIM_SUPPORT;
+ device->max_lba_range_entry_blocks = identify->max_lba_range_entry_blocks;
+ }
+
+ if (identify->additional_supported
+ & ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_DETERMINISTIC_READ)
+ {
+ capabilities |= SATI_DEVICE_CAP_DETERMINISTIC_READ_AFTER_TRIM;
+ }
+
+ if (identify->additional_supported
+ & ATA_IDENTIFY_COMMAND_ADDL_SUPPORTED_READ_ZERO)
+ {
+ capabilities |= SATI_DEVICE_CAP_READ_ZERO_AFTER_TRIM;
+ }
+
+ if (identify->capabilities1
+ & ATA_IDENTIFY_CAPABILITIES1_STANDBY_ENABLE)
+ {
+ capabilities |= SATI_DEVICE_CAP_STANDBY_ENABLE;
+ }
+
+ device->min_blocks_per_microcode_command = identify->min_num_blocks_per_microcode;
+ device->max_blocks_per_microcode_command = identify->max_num_blocks_per_microcode;
+
+ device->capabilities = capabilities;
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_device.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_device.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,203 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_DEVICE_H_
+#define _SATI_DEVICE_H_
+
+/**
+ * @file
+ * @brief This file contains all of the defintions for the SATI remote
+ * device object. Some translations require information to be
+ * remembered on a per device basis. This information is stored
+ * in the object defined in this file.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/intel_ata.h>
+
+/**
+ * @enum _SATI_DEVICE_STATE
+ *
+ * @brief This enumeration depicts the various states possible for the a
+ * translation remote device object.
+ */
+typedef enum _SATI_DEVICE_STATE
+{
+ SATI_DEVICE_STATE_OPERATIONAL,
+ SATI_DEVICE_STATE_STOPPED,
+ SATI_DEVICE_STATE_STANDBY,
+ SATI_DEVICE_STATE_IDLE,
+ SATI_DEVICE_STATE_DEVICE_FAULT_OCCURRED,
+ SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS,
+ SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS,
+ SATI_DEVICE_STATE_SEQUENCE_INCOMPLETE,
+ SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION
+
+} SATI_DEVICE_STATE;
+
+/**
+ * @name SATI_DEVICE_CAPABILITIES
+ *
+ * These constants define the various capabilities that a remote device may
+ * support for which there is an impact on translation.
+ */
+/*@{*/
+#define SATI_DEVICE_CAP_UDMA_ENABLE 0x00000001
+#define SATI_DEVICE_CAP_NCQ_REQUESTED_ENABLE 0x00000002
+#define SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE 0x00000004
+#define SATI_DEVICE_CAP_48BIT_ENABLE 0x00000008
+#define SATI_DEVICE_CAP_DMA_FUA_ENABLE 0x00000010
+#define SATI_DEVICE_CAP_SMART_SUPPORT 0x00000020
+#define SATI_DEVICE_CAP_REMOVABLE_MEDIA 0x00000040
+#define SATI_DEVICE_CAP_SMART_ENABLE 0x00000080
+#define SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE 0x00000100
+#define SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR 0x00000200
+#define SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT 0x00000400
+#define SATI_DEVICE_CAP_SSD 0x00000800
+#define SATI_DEVICE_CAP_DSM_TRIM_SUPPORT 0x00001000
+#define SATI_DEVICE_CAP_DETERMINISTIC_READ_AFTER_TRIM 0x00002000
+#define SATI_DEVICE_CAP_READ_ZERO_AFTER_TRIM 0x00004000
+#define SATI_DEVICE_CAP_STANDBY_ENABLE 0x00008000
+#define SATI_DEVICE_CAP_IGNORE_FUA 0x00010000
+
+
+/*@}*/
+
+/**
+ * @struct SATI_DEVICE
+ *
+ * @brief The SATI_DEVICE structure define the state of the remote device
+ * with respect to translation.
+ */
+typedef struct SATI_DEVICE
+{
+ /**
+ * This field simply dictates the state of the SATI device.
+ */
+ SATI_DEVICE_STATE state;
+
+ /**
+ * This field indicates features supported by the remote device that
+ * impact translation execution.
+ */
+ U16 capabilities;
+
+ /**
+ * This field indicates the depth of the native command queue supported
+ * by the device.
+ */
+ U8 ncq_depth;
+
+ /**
+ * This field stores the additional sense code for a unit attention
+ * condition.
+ */
+ U8 unit_attention_asc;
+
+ /**
+ * This field indicates the additional sense code qualifier for a unit
+ * attention condition.
+ */
+ U8 unit_attention_ascq;
+
+ /**
+ * This field indicates the ATA standby timer value set throught the
+ * ATA IDLE and ATA Standby commands
+ */
+ U8 ata_standby_timer;
+
+ /**
+ * This field indicates the maximum number of data set management
+ * descriptor entries the device supports in blocks.
+ */
+ U16 max_lba_range_entry_blocks;
+
+ /**
+ * The field is the reported logical block size for the device
+ */
+ U32 logical_block_size;
+
+ /**
+ * This field is the maximum number of blocks per Download Microcode command
+ * for this device.
+ */
+ U16 max_blocks_per_microcode_command;
+
+ /**
+ * This field is the minimum number of blocks per Download Microcode command
+ * for this device.
+ */
+ U16 min_blocks_per_microcode_command;
+
+ /**
+ * This field indicates the type of constructed sense data if enabled descriptor
+ * sense data will be constructed
+ */
+ U8 descriptor_sense_enable;
+
+} SATI_DEVICE_T;
+
+void sati_device_construct(
+ SATI_DEVICE_T * device,
+ BOOL is_ncq_enabled,
+ U8 max_ncq_depth,
+ BOOL ignore_fua
+);
+
+void sati_device_update_capabilities(
+ SATI_DEVICE_T * device,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify
+);
+
+#endif // _SATI_TRANSLATOR_SEQUENCE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_inquiry.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_inquiry.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,799 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations required to
+ * translate the SCSI inquiry command.
+ * The following (VPD) pages are currently supported:
+ * - Standard
+ * - Supported Pages
+ * - Unit Serial Number
+ * - Device Identification
+ */
+
+#if !defined(DISABLE_SATI_INQUIRY)
+
+#include <dev/isci/scil/sati_inquiry.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+/**
+* @brief This method builds the SCSI data associated with the SATI product
+* revision that is commonly used on the Standard inquiry response and
+* the ATA information page.
+*
+* @param[in] sequence This parameter specifies the translator sequence
+* object to be utilized during data translation.
+* @param[in] ata_input_data This parameter specifies ata data received from
+* the remote device.
+* @param[out] scsi_io This parameter specifies the user IO request for
+* which to construct the standard inquiry data.
+*
+* @return none
+*/
+static
+void sati_inquiry_construct_product_revision(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ // Fill in the product revision level field.
+ // Per SAT, copy portions of the firmware revision that is not filled
+ // with spaces. Some devices left-align their firmware rev ID, while
+ // others right-align.
+ if ( (identify->firmware_revision[4] == 0x20)
+ && (identify->firmware_revision[5] == 0x20)
+ && (identify->firmware_revision[6] == 0x20)
+ && (identify->firmware_revision[7] == 0x20) )
+ {
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 32,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision),
+ 4,
+ TRUE
+ );
+ }
+ else
+ {
+ // Since the last 4 bytes of the firmware revision are not spaces,
+ // utilize these bytes as the firmware revision in the inquiry data.
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 32,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(firmware_revision)+4,
+ 4,
+ TRUE
+ );
+ }
+}
+
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method builds the SCSI data associated with a SCSI standard
+ * inquiry request.
+ *
+ * @param[in] sequence This parameter specifies the translator sequence
+ * object to be utilized during data translation.
+ * @param[in] ata_input_data This parameter specifies ata data received from
+ * the remote device.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ * which to construct the standard inquiry data.
+ *
+ * @return none
+ */
+void sati_inquiry_standard_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U32 index;
+
+ // Device type is disk, attached to this lun.
+ sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+ // If the device indicates it's a removable media device, then set the
+ // RMB bit
+ if (identify->general_config_bits & ATA_IDENTIFY_REMOVABLE_MEDIA_ENABLE)
+ sati_set_data_byte(sequence, scsi_io, 1, 0x80);
+ else
+ sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+ sati_set_data_byte(sequence, scsi_io, 2, 0x05); // Indicate SPC-3 support
+ sati_set_data_byte(sequence, scsi_io, 3, 0x02); // Response Format SPC-3
+
+ sati_set_data_byte(sequence, scsi_io, 4, 62); // 62 Additional Data Bytes.
+ // n-4 per the spec, we end at
+ // byte 66, so 66-4.
+ sati_set_data_byte(sequence, scsi_io, 5, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 6, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 7, 0x02); // Enable Cmd Queueing
+
+ // The Vender identification field is set to "ATA "
+ sati_set_data_byte(sequence, scsi_io, 8, 0x41);
+ sati_set_data_byte(sequence, scsi_io, 9, 0x54);
+ sati_set_data_byte(sequence, scsi_io, 10, 0x41);
+ sati_set_data_byte(sequence, scsi_io, 11, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 12, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 13, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 14, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 15, 0x20);
+
+ // Fill in the product ID field.
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 16,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
+ 16,
+ TRUE
+ );
+
+ sati_inquiry_construct_product_revision(
+ sequence,
+ ata_input_data,
+ scsi_io
+ );
+
+ // Set the remaining fields up to the version descriptors to 0.
+ for (index = 36; index < 58; index++)
+ sati_set_data_byte(sequence, scsi_io, index, 0);
+
+ // Add version descriptors for the various protocols in play.
+
+ // SAM-4
+ sati_set_data_byte(sequence, scsi_io, 58, 0);
+ sati_set_data_byte(sequence, scsi_io, 59, 0x80);
+
+ // SAS-2
+ sati_set_data_byte(sequence, scsi_io, 60, 0x0C);
+ sati_set_data_byte(sequence, scsi_io, 61, 0x20);
+
+ // SPC-4
+ sati_set_data_byte(sequence, scsi_io, 62, 0x04);
+ sati_set_data_byte(sequence, scsi_io, 63, 0x60);
+
+ // SBC-3
+ sati_set_data_byte(sequence, scsi_io, 64, 0x04);
+ sati_set_data_byte(sequence, scsi_io, 65, 0xC0);
+
+ // ATA/ATAPI-8 ACS
+ sati_set_data_byte(sequence, scsi_io, 66, 0x16);
+ sati_set_data_byte(sequence, scsi_io, 67, 0x23);
+}
+
+/**
+ * @brief This method builds the SCSI data associated with an SCSI inquiry
+ * for the supported VPD pages page.
+ *
+ * @param[in] sequence This parameter specifies the translator sequence
+ * object to be utilized during data translation.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ * which to construct the supported VPD page information.
+ *
+ * @return none
+ */
+static
+void sati_inquiry_supported_pages_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ // Formulate the SCSI output data for the caller.
+ sati_set_data_byte(sequence, scsi_io, 0, 0); // Qualifier and Device Type
+ sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 2, 0); // Reserved.
+ sati_set_data_byte(sequence, scsi_io, 3, 4); // # VPD pages supported
+ sati_set_data_byte(sequence, scsi_io, 4, SCSI_INQUIRY_SUPPORTED_PAGES_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 5, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 6, SCSI_INQUIRY_DEVICE_ID_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 7, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 8, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 9, 0); // End of the list
+}
+
+/**
+ * @brief This method builds the SCSI data associated with a request for
+ * the unit serial number vital product data (VPD) page.
+ *
+ * @param[in] sequence This parameter specifies the translator sequence
+ * object to be utilized during data translation.
+ * @param[in] ata_input_data This parameter specifies ata data received from
+ * the remote device.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ * which to construct the unit serial number data.
+ *
+ * @return none
+ */
+void sati_inquiry_serial_number_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ // Peripheral qualifier (0x0, currently connected)
+ // Peripheral device type (0x0 direct-access block device)
+ sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+ sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 2, 0x00); // Reserved
+ sati_set_data_byte(sequence, scsi_io, 3, ATA_IDENTIFY_SERIAL_NUMBER_LEN);
+
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 4,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
+ ATA_IDENTIFY_SERIAL_NUMBER_LEN,
+ TRUE
+ );
+}
+
+/**
+* @brief This method builds the SCSI data associated with a request for
+* the Block Device Characteristics vital product data (VPD) page.
+*
+* @param[in] sequence This parameter specifies the translator sequence
+* object to be utilized during data translation.
+* @param[in] ata_input_data This parameter specifies ata data received from
+* the remote device.
+* @param[out] scsi_io This parameter specifies the user IO request for
+* which to construct the unit serial number data.
+*
+* @return none
+*/
+void sati_inquiry_block_device_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U32 offset;
+
+ // Peripheral qualifier (0x0, currently connected)
+ // Peripheral device type (0x0 direct-access block device)
+ sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+ sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_BLOCK_DEVICE_PAGE);
+
+ //PAGE LENGTH 0x003C
+ sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 3, SCSI_INQUIRY_BLOCK_DEVICE_LENGTH);
+
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 4,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(nominal_media_rotation_rate),
+ 2,
+ FALSE
+ );
+
+ sati_set_data_byte(sequence, scsi_io, 6, 0x00);
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 7,
+ (identify->device_nominal_form_factor & 0x0F) // only need bits 0-3
+ );
+
+ //bytes 8-63 are reserved
+ for(offset = 8; offset < 63; offset++)
+ {
+ sati_set_data_byte(sequence, scsi_io, offset, 0x00);
+ }
+}
+
+/**
+ * @brief This method builds the SCSI data associated with a request for
+ * the device identification vital product data (VPD) page.
+ *
+ * @param[in] sequence This parameter specifies the translator sequence
+ * object to be utilized during data translation.
+ * @param[in] ata_input_data This parameter specifies ata data received from
+ * the remote device.
+ * @param[out] scsi_io This parameter specifies the user IO request for
+ * which to construct the device ID page.
+ *
+ * @return none
+ */
+void sati_inquiry_device_id_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U16 byte_offset = 4;
+ U16 page_length;
+
+ // Peripheral qualifier (0x0, currently connected)
+ // Peripheral device type (0x0 direct-access block device)
+ sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+ sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_DEVICE_ID_PAGE);
+
+ /**
+ * If World Wide Names are supported by this target, then build an
+ * identification descriptor using the WWN.
+ */
+
+ if (identify->command_set_supported_extention
+ & ATA_IDENTIFY_COMMAND_SET_WWN_SUPPORT_ENABLE)
+ {
+
+ sati_set_data_byte(sequence,
+ scsi_io, 4, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
+ );
+
+
+ sati_set_data_byte(sequence,
+ scsi_io, 5, SCSI_LUN_ASSOCIATION | SCSI_NAA_IDENTIFIER_TYPE
+ );
+
+ sati_set_data_byte(sequence, scsi_io, 6, 0);
+ sati_set_data_byte(sequence, scsi_io, 7, 0x08); // WWN are 8 bytes long
+
+ // Copy data from the identify device world wide name field into the
+ // buffer.
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 8,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(world_wide_name),
+ ATA_IDENTIFY_WWN_LEN,
+ FALSE
+ );
+
+ byte_offset = 16;
+ }
+
+ /**
+ * Build a identification descriptor using the model number & serial number.
+ */
+
+ sati_set_data_byte(sequence,
+ scsi_io, byte_offset, SCSI_FC_PROTOCOL_IDENTIFIER | SCSI_ASCII_CODE_SET
+ );
+ byte_offset++;
+ sati_set_data_byte(sequence,
+ scsi_io, byte_offset, SCSI_LUN_ASSOCIATION | SCSI_T10_IDENTIFIER_TYPE
+ );
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
+ byte_offset++;
+
+ // Identifier length (8 bytes for "ATA " + 40 bytes from ATA IDENTIFY
+ // model number field + 20 bytes from ATA IDENTIFY serial number field.
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ byte_offset,
+ 8 + (ATA_IDENTIFY_SERIAL_NUMBER_LEN) + (ATA_IDENTIFY_MODEL_NUMBER_LEN)
+ );
+ byte_offset++;
+
+ // Per SAT, write "ATA ".
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x54);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x41);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0x20);
+ byte_offset++;
+
+ // Copy data from the identify device model number field into the
+ // buffer and update the byte_offset.
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ byte_offset,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
+ ATA_IDENTIFY_MODEL_NUMBER_LEN,
+ TRUE
+ );
+
+ byte_offset += ATA_IDENTIFY_MODEL_NUMBER_LEN;
+
+ // Copy data from the identify device serial number field into the
+ // buffer and update the byte_offset.
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ byte_offset,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(serial_number),
+ ATA_IDENTIFY_SERIAL_NUMBER_LEN,
+ TRUE
+ );
+
+ byte_offset += ATA_IDENTIFY_SERIAL_NUMBER_LEN;
+
+ /**
+ * If the target is contained in a SAS Domain, then build a target port
+ * ID descriptor using the SAS address.
+ */
+
+#if defined(SATI_TRANSPORT_SUPPORTS_SAS) \
+ && defined(DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT)
+ {
+ SCI_SAS_ADDRESS_T sas_address;
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ byte_offset,
+ SCSI_SAS_PROTOCOL_IDENTIFIER | SCSI_BINARY_CODE_SET
+ );
+ byte_offset++;
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ byte_offset,
+ SCSI_PIV_ENABLE | SCSI_TARGET_PORT_ASSOCIATION |
+ SCSI_NAA_IDENTIFIER_TYPE
+ );
+
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 0);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, 8); // SAS Addr=8 bytes
+ byte_offset++;
+
+ sati_cb_device_get_sas_address(scsi_io, &sas_address);
+
+ // Store the SAS address in the target port descriptor.
+ sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.high);
+ byte_offset += 4;
+ sati_set_data_dword(sequence, scsi_io, byte_offset, sas_address.low);
+ byte_offset += 4;
+ }
+#endif // SATI_TRANSPORT_SUPPORTS_SAS && DISABLE_MSFT_SCSI_COMPLIANCE_SUPPORT
+
+ /**
+ * Set the Page length field. The page length is n-3, where n is the
+ * last offset in the page (considered page length - 4).
+ */
+
+ page_length = byte_offset - 4;
+ sati_set_data_byte(sequence, scsi_io, 2, (U8)((page_length & 0xFF00) >> 8));
+ sati_set_data_byte(sequence, scsi_io, 3, (U8)(page_length & 0x00FF));
+}
+
+/**
+* @brief This method builds the SCSI data associated with a request for
+* the ATA information vital product data (VPD) page.
+*
+* @param[in] sequence This parameter specifies the translator sequence
+* object to be utilized during data translation.
+* @param[in] ata_input_data This parameter specifies ata data received from
+* a identify device command processed by the remote device.
+* @param[out] scsi_io This parameter specifies the user IO request for
+* which to construct the ATA information page.
+*
+* @return none
+*/
+SATI_STATUS sati_inquiry_ata_information_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 1, SCSI_INQUIRY_ATA_INFORMATION_PAGE);
+ sati_set_data_byte(sequence, scsi_io, 2, 0x02);
+ sati_set_data_byte(sequence, scsi_io, 3, 0x38);
+
+ //Reserved SAT2r07
+ sati_set_data_byte(sequence, scsi_io, 4, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 5, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 6, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 7, 0x00);
+
+ // The Vender identification field is set to "ATA "
+ sati_set_data_byte(sequence, scsi_io, 8, 0x41);
+ sati_set_data_byte(sequence, scsi_io, 9, 0x54);
+ sati_set_data_byte(sequence, scsi_io, 10, 0x41);
+ sati_set_data_byte(sequence, scsi_io, 11, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 12, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 13, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 14, 0x20);
+ sati_set_data_byte(sequence, scsi_io, 15, 0x20);
+
+ //SAT Product identification
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 16,
+ ata_input_data,
+ ATA_IDENTIFY_DEVICE_GET_OFFSET(model_number),
+ 16,
+ TRUE
+ );
+
+ //SAT Product Revision level bytes 32-35
+ sati_inquiry_construct_product_revision(
+ sequence,
+ ata_input_data,
+ scsi_io
+ );
+
+ //skipping ATA device signature for now
+
+ //Command code
+ sati_set_data_byte(sequence, scsi_io, 56, 0xEC);
+
+ //Reserved SAT2r07
+ sati_set_data_byte(sequence, scsi_io, 57, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 58, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 59, 0x00);
+
+ //copy all ATA identify device data
+ sati_ata_identify_device_copy_data(
+ sequence,
+ scsi_io,
+ 60,
+ ata_input_data,
+ 0,
+ sizeof(ATA_IDENTIFY_DEVICE_DATA_T),
+ FALSE
+ );
+
+ //Need to send ATA Execute Device Diagnostic command still
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+
+ return SATI_SEQUENCE_INCOMPLETE;
+}
+
+/**
+ * @brief This method will translate the inquiry SCSI command into
+ * an ATA IDENTIFY DEVICE command. It will handle several different
+ * VPD pages and the standard inquiry page.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * the page isn't supported, or the page code
+ * field is not zero when the EVPD bit is 0.
+ */
+SATI_STATUS sati_inquiry_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ /**
+ * SPC dictates:
+ * - that the page code field must be 0, if VPD enable is 0.
+ */
+ if ( ((sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE) == 0)
+ && (sati_get_cdb_byte(cdb, 2) != 0) )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // Set the data length based on the allocation length field in the CDB.
+ sequence->allocation_length = (sati_get_cdb_byte(cdb, 3) << 8) |
+ (sati_get_cdb_byte(cdb, 4));
+
+ // Check to see if there was a request for the vital product data or just
+ // the standard inquiry.
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_INQUIRY_EVPD_ENABLE)
+ {
+ // Parse the page code to determine which translator to invoke.
+ switch (sati_get_cdb_byte(cdb, 2))
+ {
+ case SCSI_INQUIRY_SUPPORTED_PAGES_PAGE:
+ sequence->type = SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES;
+ sati_inquiry_supported_pages_translate_data(sequence, scsi_io);
+ return SATI_COMPLETE;
+ break;
+
+ case SCSI_INQUIRY_UNIT_SERIAL_NUM_PAGE:
+ sequence->type = SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER;
+ break;
+
+ case SCSI_INQUIRY_DEVICE_ID_PAGE:
+ sequence->type = SATI_SEQUENCE_INQUIRY_DEVICE_ID;
+ break;
+
+ case SCSI_INQUIRY_ATA_INFORMATION_PAGE:
+
+ if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ sati_ata_execute_device_diagnostic_construct(
+ ata_io,
+ sequence
+ );
+ sequence->type = SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_INQUIRY_ATA_INFORMATION;
+ }
+ break;
+
+ case SCSI_INQUIRY_BLOCK_DEVICE_PAGE:
+ sequence->type = SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE;
+ break;
+
+ default:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_INQUIRY_STANDARD;
+ }
+
+ sati_ata_identify_device_construct(ata_io, sequence);
+
+ return SATI_SUCCESS;
+}
+
+/**
+* @brief This method finishes the construction of the SCSI data associated
+ with a request for the ATA information vital product data (VPD) page.
+ The ATA device signature is written into the data response from the
+ task fle registers after issuing a Execute Device Diagnostic command.
+*
+* @param[in] sequence This parameter specifies the translator sequence
+* object to be utilized during data translation.
+* @param[out] scsi_io This parameter specifies the user IO request for
+* which to construct the ATA information page.
+* @param[in] ata_io This parameter specifies the ATA payload
+* buffer location and size to be translated.
+*
+* @return none
+*/
+void sati_inquiry_ata_information_finish_translation(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U32 offset;
+
+ //SATA transport
+ sati_set_data_byte(sequence, scsi_io, 36, 0x34);
+ sati_set_data_byte(sequence, scsi_io, 37, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 38, (U8) sati_get_ata_status(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 39, (U8) sati_get_ata_error(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 40, sati_get_ata_lba_low(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 41, sati_get_ata_lba_mid(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 42, sati_get_ata_lba_high(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 43, sati_get_ata_device(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 44, sati_get_ata_lba_low_ext(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 45, sati_get_ata_lba_mid_ext(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 46, sati_get_ata_lba_high_ext(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 47, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 48, sati_get_ata_sector_count(register_fis));
+ sati_set_data_byte(sequence, scsi_io, 49, sati_get_ata_sector_count_exp(register_fis));
+
+ for(offset = 50; offset < 56; offset++)
+ {
+ sati_set_data_byte(sequence, scsi_io, offset, 0x00);
+ }
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+}
+
+#endif // !defined(DISABLE_SATI_INQUIRY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_inquiry.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_inquiry.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,114 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_INQUIRY_H_
+#define _SATI_INQUIRY_H_
+
+/**
+ * @file
+ *
+ * @brief This file contains the method prototypes required to
+ * translate the SCSI inquiry command.
+ * The following (VPD) pages are currently supported:
+ * - Standard
+ * - Supported Pages
+ * - Unit Serial Number
+ * - Device Identification
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+void sati_inquiry_standard_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_inquiry_serial_number_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_inquiry_device_id_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_inquiry_block_device_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+SATI_STATUS sati_inquiry_ata_information_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+SATI_STATUS sati_inquiry_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * translator_sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+void sati_inquiry_ata_information_finish_translation(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_INQUIRY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_log_sense.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_log_sense.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,807 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the method definitions to translate
+* SCSI Log Sense command based of the SATv2 spec.
+*/
+
+#if !defined(DISABLE_SATI_LOG_SENSE)
+
+#include <dev/isci/scil/sati_log_sense.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method constructs the SATI supported log page. This is a log
+ * containing the page codes of all the SATI supported log pages.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_supported_log_page_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ U32 next_byte;
+ //set SPF = 0 and PAGE_CODE = 0
+ sati_set_data_byte(sequence, scsi_io, 0, 0x00);
+
+ //set SUBPAGE_CODE = 0
+ sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+ //set the Page Length to (n-3) or 2 because only two log pages are supported
+ sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 3, 0x02);
+
+ //specify the next byte to be set
+ next_byte = 4;
+
+ if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
+ {
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ next_byte,
+ SCSI_LOG_PAGE_INFORMATION_EXCEPTION
+ );
+ next_byte = 5;
+ }
+
+ if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT)
+ {
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ next_byte,
+ SCSI_LOG_PAGE_SELF_TEST
+ );
+ }
+}
+
+/**
+ * @brief This method sets bytes 4-19 of the self-test log parameter to zero.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_set_parameters_to_zero(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ sati_set_data_byte(sequence, scsi_io, 8, 0x00); //log_parameter byte 4
+ sati_set_data_byte(sequence, scsi_io, 9, 0x00); //log_parameter byte 5
+ sati_set_data_byte(sequence, scsi_io, 10, 0x00); //log_parameter byte 6
+ sati_set_data_byte(sequence, scsi_io, 11, 0x00); //log_parameter byte 7
+ sati_set_data_byte(sequence, scsi_io, 12, 0x00); //log_parameter byte 8
+ sati_set_data_byte(sequence, scsi_io, 13, 0x00); //log_parameter byte 9
+ sati_set_data_byte(sequence, scsi_io, 14, 0x00); //log_parameter byte 10
+ sati_set_data_byte(sequence, scsi_io, 15, 0x00); //log_parameter byte 11
+ sati_set_data_byte(sequence, scsi_io, 16, 0x00); //log_parameter byte 12
+ sati_set_data_byte(sequence, scsi_io, 17, 0x00); //log_parameter byte 13
+ sati_set_data_byte(sequence, scsi_io, 18, 0x00); //log_parameter byte 14
+ sati_set_data_byte(sequence, scsi_io, 19, 0x00); //log_parameter byte 15
+ sati_set_data_byte(sequence, scsi_io, 20, 0x00); //log_parameter byte 16
+ sati_set_data_byte(sequence, scsi_io, 21, 0x00); //log_parameter byte 17
+ sati_set_data_byte(sequence, scsi_io, 22, 0x00); //log_parameter byte 18
+ sati_set_data_byte(sequence, scsi_io, 23, 0x00); //log_parameter byte 19
+}
+
+/**
+ * @brief This method translates the ATA Extended SMART self-test log into
+ * SCSI Sense Key, Additional Sense Code, and Additional Sense code
+ * qualifiers based on the self test status byte in the appropriate
+ * descriptor entry.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_translate_sense_values(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 self_test_status_byte
+)
+{
+ //byte 17
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 21,
+ SCSI_DIAGNOSTIC_FAILURE_ON_COMPONENT
+ );
+
+ switch(self_test_status_byte)
+ {
+ case 1:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x81);
+ break;
+
+ case 2:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x82);
+ break;
+
+ case 3:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_ABORTED_COMMAND);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x83);
+ break;
+
+ case 4:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x84);
+ break;
+
+ case 5:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x85);
+ break;
+
+ case 6:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x86);
+ break;
+
+ case 7:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_MEDIUM_ERROR);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x87);
+ break;
+
+ case 8:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_HARDWARE_ERROR);
+
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x88);
+ break;
+
+ default:
+ //byte 16
+ sati_set_data_byte(sequence, scsi_io, 20, SCSI_SENSE_NO_SENSE);
+ //byte 17
+ sati_set_data_byte(sequence, scsi_io, 21, SCSI_ASC_NO_ADDITIONAL_SENSE);
+ //byte 18
+ sati_set_data_byte(sequence, scsi_io, 22, 0x00);
+ break;
+ }
+
+}
+
+/**
+ * @brief This method retrieves the correct self-test results by checking the
+ * descriptor index in the extended SMART self-test log. The index is
+ * used to determine the appropriate descriptor entry.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_get_self_test_results(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log
+)
+{
+ U16 descriptor_index = *((U16 *)(&ata_log->self_test_descriptor_index[0]));
+
+ /*
+ * SATv2 wants data from descriptor N where N is equal to
+ * (descriptor_index - parameter_code) + 1. Since parameter
+ * code is always 0x0001 just checking descriptor_index.
+ */
+
+ if(descriptor_index <= 0)
+ {
+ sati_set_parameters_to_zero(sequence, scsi_io);
+ }
+ else
+ {
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 8,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
+ );
+
+ //Sef-test number unspecified per satv2
+ sati_set_data_byte(sequence, scsi_io, 9, 0x00);
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 10,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_high
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 11,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.time_stamp_low
+ );
+
+ //set to zero because it's a 48bit address
+ sati_set_data_byte(sequence, scsi_io, 12, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 13, 0x00);
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 14,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high_ext
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 15,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid_ext
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 16,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low_ext
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 17,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_high
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 18,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_mid
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 19,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.failing_lba_low
+ );
+
+ sati_translate_sense_values(
+ sequence,
+ scsi_io,
+ ata_log->descriptor_entrys[descriptor_index].DESCRIPTOR_ENTRY.status_byte
+ );
+ }
+}
+
+/**
+* @brief This method will construct the first eight bytes of the SCSI self test
+* log page for both cases when SATI sends a ATA read log ext and a smart
+* read log command.
+*
+* @return n/a
+*
+*/
+static
+void sati_self_test_log_header_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ //PAGE CODE for Self-Test Log Page
+ sati_set_data_byte(sequence, scsi_io, 0, 0x10);
+ sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+ //PAGE LENGTH is 0x14 instead of 0x190, not returning 20/0x190 log perameters
+ sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 3, 0x14);
+
+ /*
+ * Log PARAMETER 0x0001
+ * Only sending one log parameter per self-test request.
+ */
+ sati_set_data_byte(sequence, scsi_io, 4, 0x00); //log_parameter byte 0
+ sati_set_data_byte(sequence, scsi_io, 5, 0x01); //log_parameter byte 1
+
+ //Set to 0x03 per SATv2 spec
+ sati_set_data_byte(sequence, scsi_io, 6, 0x03); //log_parameter byte 2
+
+ //Parameter Length set to 0x10 per SATv2 spec
+ sati_set_data_byte(sequence, scsi_io, 7, 0x10); //log_parameter byte 3
+}
+
+/**
+ * @brief This method will construct the SCSI self test log page from
+ * the Extended SMART self-test log response recieved from the
+ * ATA device. The response is from a ATA_Read_Log_EXT command
+ * issued by SATI.
+ *
+ * @return n/a
+ *
+ */
+static
+void sati_extended_self_test_log_page_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_data
+)
+{
+ ATA_EXTENDED_SMART_SELF_TEST_LOG_T * ata_log =
+ (ATA_EXTENDED_SMART_SELF_TEST_LOG_T*) ata_data;
+
+ sati_self_test_log_header_construct(sequence, scsi_io);
+
+ //bytes 4-19
+ if( (ata_log->self_test_descriptor_index[0] == 0) &&
+ (ata_log->self_test_descriptor_index[1] == 0))
+ {
+ sati_set_parameters_to_zero(sequence, scsi_io);
+ }
+ else
+ {
+ sati_get_self_test_results(sequence, scsi_io, ata_log);
+ }
+}
+
+/**
+* @brief This method will construct the SCSI self test log page from
+* the SMART self-test log response recieved from the ATA device.
+* The response is from a ATA_SMART_Read_Log command issued by SATI.
+*
+* @return n/a
+*
+*/
+static
+void sati_self_test_log_page_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_data
+)
+{
+ ATA_SMART_SELF_TEST_LOG_T * ata_log =
+ (ATA_SMART_SELF_TEST_LOG_T*) ata_data;
+
+ sati_self_test_log_header_construct(sequence, scsi_io);
+
+ //first descriptor entry(index == 0) is always used because scsi_parameter_code == 1
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 8,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
+ );
+
+ //Sef-test number unspecified per satv2
+ sati_set_data_byte(sequence, scsi_io, 9, 0x00);
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 10,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_high
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 11,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.time_stamp_low
+ );
+
+ //set to zero because it's a 28bit address
+ sati_set_data_byte(sequence, scsi_io, 12, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 13, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 14, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 15, 0x00);
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 16,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low_ext
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 17,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_high
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 18,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_mid
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 19,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.failing_lba_low
+ );
+
+ sati_translate_sense_values(
+ sequence,
+ scsi_io,
+ ata_log->descriptor_entrys[0].SMART_DESCRIPTOR_ENTRY.status_byte
+ );
+}
+
+/**
+* @brief This method will construct the SCSI information exception log page from
+* the ATA SMART response recieved from the ATA device. The response is
+* from a ATA SMART return status command issued by SATI.
+*
+* @return n/a
+*
+*/
+static
+void sati_information_exception_log_page_contruct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U32 mid_register = sati_get_ata_lba_mid(register_fis);
+ U32 high_register = sati_get_ata_lba_high(register_fis);
+
+ //Information Exception Page code
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 0,
+ SCSI_LOG_PAGE_INFORMATION_EXCEPTION
+ );
+
+ //Sub-page code
+ sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+
+ //Page length of log parameters
+ sati_set_data_byte(sequence, scsi_io, 2, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 3, 0x08);
+
+ //parameter code
+ sati_set_data_byte(sequence, scsi_io, 4, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 5, 0x00);
+
+ //Format and Linking
+ sati_set_data_byte(sequence, scsi_io, 6, 0x03);
+ //Parameter Length
+ sati_set_data_byte(sequence, scsi_io, 7, 0x04);
+
+ if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
+ && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
+ {
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 8,
+ SCSI_ASC_HARDWARE_IMPENDING_FAILURE
+ );
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 9,
+ SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
+ );
+ }
+ else
+ {
+ sati_set_data_byte(sequence, scsi_io, 8, SCSI_ASC_NO_ADDITIONAL_SENSE);
+ sati_set_data_byte(sequence, scsi_io, 9, SCSI_ASCQ_NO_ADDITIONAL_SENSE);
+ }
+ //setting most recent temperature reading to 0xFF(not supported) for now.
+ sati_set_data_byte(sequence, scsi_io, 10, 0xFF);
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI Log Sense command into ATA commands
+ * specified by SATv2. ATA commands Read Log EXT and SMART Read Log will
+ * be issued by this translation.
+ *
+ * @return SATI_STATUS Indicates if the command translation succeeded.
+ *
+ */
+SATI_STATUS sati_log_sense_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ SATI_STATUS status = SATI_FAILURE;
+
+ if(SATI_LOG_SENSE_GET_PC_FIELD(cdb) == 1 &&
+ (sati_get_cdb_byte(cdb, 3) == 0))
+ {
+ sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8));
+
+ switch(SATI_LOG_SENSE_GET_PAGE_CODE(cdb))
+ {
+ //Return Supported Log Pages log page
+ case SCSI_LOG_PAGE_SUPPORTED_PAGES :
+ sati_supported_log_page_construct(sequence, scsi_io);
+ sequence->type = SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE;
+ status = SATI_COMPLETE;
+ break;
+
+ //Return Self-Test Results log page
+ case SCSI_LOG_PAGE_SELF_TEST :
+
+ if((sequence->device->capabilities &
+ SATI_DEVICE_CAP_SMART_SELF_TEST_SUPPORT) == 0)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ //check if 48-bit Address feature set is supported
+ if((sequence->device->capabilities &
+ SATI_DEVICE_CAP_48BIT_ENABLE))
+ {
+ //ATA Read Log Ext with log address set to 0x07
+ sati_ata_read_log_ext_construct(
+ ata_io,
+ sequence,
+ ATA_LOG_PAGE_EXTENDED_SMART_SELF_TEST,
+ sizeof(ATA_EXTENDED_SMART_SELF_TEST_LOG_T)
+ );
+ sequence->type =
+ SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE;
+ status = SATI_SUCCESS;
+ }
+ else
+ {
+ //ATA Smart Read Log with log address set to 0x06
+ sati_ata_smart_read_log_construct(
+ ata_io,
+ sequence,
+ ATA_LOG_PAGE_SMART_SELF_TEST,
+ sizeof(ATA_SMART_SELF_TEST_LOG_T)
+ );
+ sequence->type = SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE;
+ status = SATI_SUCCESS;
+ }
+ }
+ break;
+
+ //Return Informational Exceptions log page
+ case SCSI_LOG_PAGE_INFORMATION_EXCEPTION :
+ if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
+ {
+ if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
+ {
+ sati_ata_smart_return_status_construct(
+ ata_io,
+ sequence,
+ ATA_SMART_SUB_CMD_RETURN_STATUS
+ );
+ sequence->type =
+ SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE;
+ status = SATI_SUCCESS;
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_ATA_DEVICE_FEATURE_NOT_ENABLED,
+ SCSI_ASCQ_ATA_DEVICE_FEATURE_NOT_ENABLED
+ );
+
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ break;
+ default :
+ //UNSPECIFIED SATv2r9
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_NO_ADDITIONAL_SENSE ,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+ }
+ return status;
+}
+
+/**
+ * @brief This method will translate the response to the SATI Log Sense
+ * translation. ATA command responses will be translated into the
+ * correct SCSI log pages to be returned by SATI.
+ *
+ * @return SATI_STATUS Indicates if the response translation succeeded.
+ *
+ */
+SATI_STATUS sati_log_sense_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ SATI_STATUS status = SATI_FAILURE;
+
+ if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE ,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+
+ void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+ if(ata_data == NULL)
+ {
+ return SATI_FAILURE;
+ }
+
+ switch(sequence->type)
+ {
+ case SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE:
+ sati_extended_self_test_log_page_construct(
+ sequence, scsi_io, ata_data
+ );
+
+ status = SATI_COMPLETE;
+ break;
+
+ case SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE:
+ sati_self_test_log_page_construct(sequence, scsi_io, ata_data);
+ status = SATI_COMPLETE;
+ break;
+
+ case SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE:
+ //This function needs a d->h register fis, not ata data
+ sati_information_exception_log_page_contruct(
+ sequence, scsi_io, ata_io
+ );
+
+ status = SATI_COMPLETE;
+ break;
+
+ default:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE ,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+ }
+ return status;
+}
+
+#endif // !defined(DISABLE_SATI_LOG_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_log_sense.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_log_sense.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,87 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the method declarations to translate
+ * SCSI Log Sense command based of the SATv2 spec.
+ */
+
+#ifndef _SATI_LOG_SENSE_H_
+#define _SATI_LOG_SENSE_H_
+
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_LOG_SENSE_GET_PC_FIELD(cdb) \
+ (( sati_get_cdb_byte((cdb), 2) & SCSI_LOG_SENSE_PC_FIELD_MASK ) \
+ >> SCSI_LOG_SENSE_PC_FIELD_SHIFT )
+
+#define SATI_LOG_SENSE_GET_PAGE_CODE(cdb) \
+ (( sati_get_cdb_byte((cdb), 2) & SCSI_LOG_SENSE_PAGE_CODE_FIELD_MASK ) \
+ >> SCSI_LOG_SENSE_PAGE_CODE_FIELD_SHIFT )
+
+SATI_STATUS sati_log_sense_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_log_sense_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+#endif // _SATI_LOG_SENSE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_lun_reset.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_lun_reset.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,122 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the method implementations required to
+ * translate the SCSI lun reset command.
+ */
+
+#if !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
+#include <dev/isci/scil/sati_lun_reset.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the lun reset SCSI task request into an
+ * ATA SOFT RESET command. For more information on the parameters
+ * passed to this method, please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ *
+ * @note It is up to the user of the sata translator to set the command bit
+ * and clear the control softreset bit and send the second register fis.
+ */
+SATI_STATUS sati_lun_reset_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8* register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_NOP);
+ sati_set_ata_control(register_fis, ATA_CONTROL_REG_SOFT_RESET_BIT);
+
+ //set all other fields to zero.
+ sati_clear_sata_command_flag(register_fis);
+ sati_set_ata_features(register_fis, 0);
+ sati_set_ata_features_exp(register_fis, 0);
+ sati_set_ata_sector_count(register_fis, 0);
+ sati_set_ata_sector_count_exp(register_fis, 0);
+ sati_set_ata_lba_low(register_fis, 0);
+ sati_set_ata_lba_mid(register_fis, 0);
+ sati_set_ata_lba_high(register_fis, 0);
+ sati_set_ata_lba_low_exp(register_fis, 0);
+ sati_set_ata_lba_mid_exp(register_fis, 0);
+ sati_set_ata_lba_high_exp(register_fis, 0);
+ sati_set_ata_device_head(register_fis, 0);
+
+ sequence->type = SATI_SEQUENCE_LUN_RESET;
+ sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+ sequence->protocol = SAT_PROTOCOL_SOFT_RESET;
+ sequence->ata_transfer_length = 0;
+
+ return SATI_SUCCESS;
+}
+
+#endif // !defined(DISABLE_SATI_TASK_MANAGEMENT)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_lun_reset.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_lun_reset.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,79 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_LUN_RESET_H_
+#define _SATI_LUN_RESET_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to translate the
+ * SCSI logical unit reset task request as well as translate response
+ * for the task request.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_lun_reset_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_task,
+ void * ata_io
+);
+
+void sati_lun_reset_translate_resposne(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_task
+);
+
+#endif // _SATI_LUN_RESET_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_pages.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_pages.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,372 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the mode page constants and data for the mode
+ * pages supported by this translation implementation.
+ */
+
+// DO NOT MOVE THIS INCLUDE STATEMENT! This include must occur before
+// the below check for ENABLE_SATI_MODE_PAGES.
+#include <dev/isci/scil/sati_types.h>
+
+#if defined(ENABLE_SATI_MODE_PAGES)
+
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* C O N S T A N T S
+//******************************************************************************
+
+#define SCSI_MODE_PAGE19_SAS_ID 0x6
+#define SCSI_MODE_PAGE19_SUB1_PAGE_NUM 0x1
+#define SCSI_MODE_PAGE19_SUB1_PC 0x59
+
+//******************************************************************************
+//* M O D E P A G E S
+//******************************************************************************
+
+U8 sat_default_mode_page_01[] =
+{
+ SCSI_MODE_PAGE_READ_WRITE_ERROR, // Byte 0 - Page Code, SPF(0), PS(0)
+ SCSI_MODE_PAGE_01_LENGTH-2, // Byte 1 - Page Length
+ 0x80, // Byte 2 - AWRE, ARRE, TB, RC, EER, PER, DTE, DCR
+ 0x00, // Byte 3 - Read Retry Count
+
+ 0x00, // Byte 4 - Obsolete
+ 0x00, // Byte 5 - Obsolete
+ 0x00, // Byte 6 - Obsolete
+ 0x00, // Byte 7 - Restricted for MMC-4
+
+ 0x00, // Byte 8 - Write Retry Count
+ 0x00, // Byte 9 - Reserved
+ 0x00, // Byte 10 - Recovery Time Limit
+ 0x00, // Byte 11
+};
+
+U8 sat_changeable_mode_page_01[] =
+{
+ SCSI_MODE_PAGE_READ_WRITE_ERROR,
+ SCSI_MODE_PAGE_01_LENGTH-2,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+};
+
+U8 sat_default_mode_page_02[] =
+{
+ SCSI_MODE_PAGE_DISCONNECT_RECONNECT, // Byte 0 - Page Code, SPF(0), PS(0)
+ SCSI_MODE_PAGE_02_LENGTH-2, // Byte 1 - Page Length
+ 0x00, // Byte 2 - Buffer Full Ratio
+ 0x00, // Byte 3 - Buffer Empty Ratio
+
+ 0x00, // Byte 4 - Bus Inactivity Limit
+ 0x00, // Byte 5
+ 0x00, // Byte 6 - Disconnect Time Limit
+ 0x00, // Byte 7
+
+ 0x00, // Byte 8 - Connect Time Limit
+ 0x00, // Byte 9
+ 0x00, // Byte 10 - Maximum Burst Size
+ 0x00, // Byte 11
+
+ 0x00, // Byte 12 - EMDP, FAIR_ARB, DIMM, DTDC
+ 0x00, // Byte 13
+ 0x00, // Byte 14 - First Burst Size
+ 0x00, // Byte 15
+};
+
+U8 sat_changeable_mode_page_02[] =
+{
+ SCSI_MODE_PAGE_DISCONNECT_RECONNECT,
+ SCSI_MODE_PAGE_02_LENGTH-2,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+};
+
+U8 sat_default_mode_page_08[] =
+{
+ SCSI_MODE_PAGE_CACHING, // Byte 0 - Page Code, SPF(0), PS(0)
+ SCSI_MODE_PAGE_08_LENGTH-2, // Byte 1 - Page Length
+ 0x00, // Byte 2 - IC, ABPF, CAP, DISC, SIZE, WCE(1), MF, RCD
+ 0x00, // Byte 3 - Demand Read Retention Priority, Write Retention Priority
+
+ 0x00, // Byte 4 - Disable Pre-Fetch Transfer Length
+ 0x00, // Byte 5
+ 0x00, // Byte 6 - Minimum Pre-Fetch
+ 0x00, // Byte 7
+
+ 0x00, // Byte 8 - Maximum Pre-Fetch
+ 0x00, // Byte 9
+ 0x00, // Byte 10 - Maximum Pre-Fetch Ceiling
+ 0x00, // Byte 11
+
+ 0x00, // Byte 12 - FSW, LBCSS, DRA(0), Vendor Specific, NV_DIS
+ 0x00, // Byte 13 - Number of Cache Segments
+ 0x00, // Byte 14 - Cache Segment Size
+ 0x00, // Byte 15
+
+ 0x00, // Byte 16 - Reserved
+ 0x00, // Byte 17 - Non-Cache Segment Size
+ 0x00, // Byte 18
+ 0x00, // PAD
+};
+
+U8 sat_changeable_mode_page_08[] =
+{
+ SCSI_MODE_PAGE_CACHING,
+ SCSI_MODE_PAGE_08_LENGTH-2,
+ SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00, // PAD
+};
+
+U8 sat_default_mode_page_0A[] =
+{
+ SCSI_MODE_PAGE_CONTROL, // Byte 0 - Page Code, SPF(0), PS(0)
+ SCSI_MODE_PAGE_0A_LENGTH-2, // Byte 1 - Page Length
+ 0x00, // Byte 2 - TST(0), TMF_ONLY(0), D_SENSE(0), GLTSD(0), RLEC(0)
+ 0x10, // Byte 3 - Queue Algorithm(0), QErr(0)
+
+ 0x00, // Byte 4 - TAS(0), RAC(0), UA_(0), SWP(0)
+ 0x00, // Byte 5 - ATO(0), AUTOLOAD(0)
+ 0x00, // Byte 6
+ 0x00, // Byte 7
+
+ 0xFF, // Byte 8 - Unlimited Busy timeout
+ 0xFF, // Byte 9
+ 0x00, // Byte 10 - do not support self time compl time xlation
+ 0x00, // Byte 11
+};
+
+U8 sat_changeable_mode_page_0A[] =
+{
+ SCSI_MODE_PAGE_CONTROL,
+ SCSI_MODE_PAGE_0A_LENGTH-2,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+};
+
+U8 sat_default_mode_page_19[] =
+{
+ SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT, // Byte 0 - PS, SPF, Page Code
+ SCSI_MODE_PAGE_19_LENGTH-2, // Byte 1 - Page Length
+ SCSI_MODE_PAGE19_SAS_ID, // Byte 2 - Rsvd, READY_LED, ProtoID
+ 0x00, // PAD
+
+ 0xFF, // Byte 4 - IT NLT MSB, 0xFF retry forever
+ 0xFF, // Byte 5 - IT NLT LSB, 0xFF retry forever
+ 0x00, // Byte 6 - IRT MSB, 0x0 disable init resp timer
+ 0x00, // Byte 7 - IRT LSB, 0x0 disable init resp timer
+};
+
+U8 sat_changeable_mode_page_19[] =
+{
+ SCSI_MODE_PAGE_PROTOCOL_SPECIFIC_PORT,
+ SCSI_MODE_PAGE_19_LENGTH-2,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+};
+
+U8 sat_default_mode_page_1C[] =
+{
+ SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL, // Byte 0 - Page Code,
+ // SPF(0), PS(0)
+ SCSI_MODE_PAGE_1C_LENGTH-2, // Byte 1 - Page Length
+ SCSI_MODE_PAGE_DEXCPT_ENABLE, // Byte 2 - Perf, EBF, EWasc,
+ // DExcpt(1), Test, LogErr
+ 0x06, // Byte 3 -- MRIE (6 == values only available upon request)
+
+ 0x00, // Byte 4 -- Interval Timer
+ 0x00, // Byte 5
+ 0x00, // Byte 6
+ 0x00, // Byte 7
+
+ 0x00, // Byte 8 -- Report Count
+ 0x00, // Byte 9
+ 0x00, // Byte 10
+ 0x00, // Byte 11
+};
+
+U8 sat_changeable_mode_page_1C[] =
+{
+ SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL,
+ SCSI_MODE_PAGE_1C_LENGTH-2,
+ SCSI_MODE_PAGE_DEXCPT_ENABLE,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+};
+
+U8 sat_supported_mode_pages[] =
+{
+ SCSI_MODE_PAGE_READ_WRITE_ERROR,
+ SCSI_MODE_PAGE_DISCONNECT_RECONNECT,
+ SCSI_MODE_PAGE_CACHING,
+ SCSI_MODE_PAGE_CONTROL,
+ SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL
+};
+
+U8 *sat_changeable_mode_pages[] =
+{
+ sat_changeable_mode_page_01,
+ sat_changeable_mode_page_02,
+ sat_changeable_mode_page_08,
+ sat_changeable_mode_page_0A,
+ sat_changeable_mode_page_1C
+};
+
+U8 *sat_default_mode_pages[] =
+{
+ sat_default_mode_page_01,
+ sat_default_mode_page_02,
+ sat_default_mode_page_08,
+ sat_default_mode_page_0A,
+ sat_default_mode_page_1C
+};
+
+U16 sat_mode_page_sizes[] =
+{
+ sizeof(sat_default_mode_page_01),
+ sizeof(sat_default_mode_page_02),
+ sizeof(sat_default_mode_page_08),
+ sizeof(sat_default_mode_page_0A),
+ sizeof(sat_default_mode_page_1C)
+};
+
+U16 sati_mode_page_get_page_index(
+ U8 page_code
+)
+{
+ U16 index;
+ for (index = 0; index < SAT_SUPPORTED_MODE_PAGES_LENGTH; index++)
+ {
+ if (sat_supported_mode_pages[index] == page_code)
+ return index;
+ }
+
+ return SATI_MODE_PAGE_UNSUPPORTED_INDEX;
+}
+
+#endif // defined(ENABLE_SATI_MODE_PAGES)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_pages.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_pages.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,144 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the mode page constants and members that are
+ * supported by this translation implementation.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+
+// These values represent the mode page (not including header and block
+// descriptor). The page length fields in the mode sense data are equivalent
+// to the constant values below less 2. The minus 2 is due to not including
+// the page code byte (byte 0) and the page length byte (byte 1).
+#define SCSI_MODE_PAGE_01_LENGTH 0x0C
+#define SCSI_MODE_PAGE_02_LENGTH 0x10
+#define SCSI_MODE_PAGE_08_LENGTH 0x14
+#define SCSI_MODE_PAGE_0A_LENGTH 0x0C
+#define SCSI_MODE_PAGE_19_LENGTH 0x8
+#define SCSI_MODE_PAGE_1A_LENGTH 0x0C
+#define SCSI_MODE_PAGE_1C_LENGTH 0x0C
+#define SCSI_MODE_PAGE_3F_LENGTH SCSI_MODE_PAGE_08_LENGTH \
+ + SCSI_MODE_PAGE_1C_LENGTH \
+
+#define SATI_MODE_PAGE_UNSUPPORTED_INDEX 0xFFFF
+
+#define SAT_SUPPORTED_MODE_PAGES_LENGTH sizeof(sat_supported_mode_pages)/sizeof(U8)
+
+typedef enum _RETURN_PAGE{
+ CHANGEABLE_PAGE,
+ DEFAULT_PAGE
+}RETURN_PAGE;
+
+
+/**
+ * @struct SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6
+ *
+ * @brief This structure contains mode parameter header fields for 6 byte
+ * mode select command.
+ */
+typedef struct SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6
+{
+ U8 mode_data_length;
+ U8 medium_type; //Should be 0
+ U8 device_specific_parameter;
+ U8 block_descriptor_length;
+
+}SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T;
+
+/**
+ * @struct MODE_PARAMETER_HEADER_10
+ *
+ * @brief This structure contains mode parameter header fields for 10 byte
+ * mode select command.
+ */
+typedef struct SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10
+{
+ U8 mode_data_length[2];
+ U8 medium_type; //Should be 0
+ U8 device_specific_parameter;
+ U8 long_lba;
+ U8 reserve;
+ U8 block_descriptor_length[2];
+
+}SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T;
+
+/**
+ * @struct MODE_PARAMETER_BLOCK_DESCRIPTOR
+ *
+ * @brief This structure contains mode parameter block descriptor fields.
+ */
+typedef struct SCSI_MODE_SELECT_MODE_PARAMETER_BLOCK_DESCRIPTOR
+{
+ U8 density_code;
+ U8 number_of_blocks[3];
+ U8 reserved;
+ U8 block_length[3];
+
+}SCSI_MODE_SELECT_MODE_PARAMETER_BLOCK_DESCRIPTOR_T;
+
+U16 sati_mode_page_get_page_index(
+ U8 page_code
+);
+
+U8 * sati_mode_page_get_mode_page(
+ U8 page_code,
+ RETURN_PAGE page
+);
+
+extern U8 * sat_changeable_mode_pages[];
+extern U8 * sat_default_mode_pages[];
+extern U16 sat_mode_page_sizes[];
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_select.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_select.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,1115 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI mode select (6 and 10-byte) commands with 5
+ * supported mode parameter pages (0x01, 0x02, 0x08, 0x0A, 0x1C).
+ */
+
+#if !defined(DISABLE_SATI_MODE_SELECT)
+
+#include <dev/isci/scil/sati_mode_select.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sci_object.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will get medium type parameter field per CDB size.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO object
+ * for which to calculate the mode page header.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ * associated with the CDB for which to calculate the header.
+ *
+ * @return This method returns the medium type for the mode page header.
+ */
+static
+U8 sati_mode_select_get_medium_type(
+ U8 * mode_parameters,
+ U32 cdb_size
+)
+{
+ U8 medium_type =0xFF;
+ SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T * mode_parameters_6;
+ SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T * mode_parameters_10;
+
+ if(cdb_size == 6)
+ {
+ mode_parameters_6 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T *) mode_parameters;
+ medium_type = mode_parameters_6->medium_type;
+ }
+ else if(cdb_size == 10)
+ {
+ mode_parameters_10 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T *) mode_parameters;
+ medium_type = mode_parameters_10->medium_type;
+ }
+
+ return medium_type;
+}
+
+/**
+ * @brief This method will retrieve Block Descriptor Length.
+ *
+ * @param[in] mode_parameters This parameter contains the address to the mode parameters.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ * associated with the CDB for which to process the block descriptor.
+ *
+ * @return This method returns the size, in bytes, for the mode parameter block descriptor.
+ */
+static
+U32 sati_mode_select_get_mode_block_descriptor_length(
+ U8 * mode_parameters,
+ U32 cdb_size
+)
+{
+ U32 mode_block_descriptor_length = 0;
+ SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T * mode_parameters_6;
+ SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T * mode_parameters_10;
+
+ if(cdb_size == 6)
+ {
+ mode_parameters_6 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T *) mode_parameters;
+ mode_block_descriptor_length = mode_parameters_6->block_descriptor_length;
+ }
+ else if(cdb_size == 10)
+ {
+ mode_parameters_10 = (SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T *) mode_parameters;
+ //Long LBA bit is the bit0 of the byte
+ //Spec says another way to get the block descriptor length to multiply the block number
+ // with block length (8 or 16), but we can get it directly.
+ mode_block_descriptor_length =(((U16)mode_parameters_10->block_descriptor_length[0]) << 8) +
+ mode_parameters_10->block_descriptor_length[1];
+
+ }
+
+ return mode_block_descriptor_length;
+
+}
+
+/**
+ * @brief This method will find the starting byte location for a page.
+ *
+ * @param[in] block_descriptor_length This parameter passes in the length of
+ * block descriptor.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ * associated with the CDB for which to calculate the header.
+ *
+ * @return This method returns the offset, for the mode page.
+ */
+static
+U32 sati_mode_select_get_mode_page_offset(
+ U32 block_descriptor_length,
+ U32 cdb_size
+ )
+{
+ U32 mode_page_offset;
+
+ if(cdb_size == 6)
+ {
+ mode_page_offset = sizeof(SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_6_T) + block_descriptor_length;
+ }
+ else if(cdb_size == 10)
+ {
+ mode_page_offset = sizeof(SCSI_MODE_SELECT_MODE_PARAMETER_HEADER_10_T) + block_descriptor_length;
+ }
+ else
+ {
+ mode_page_offset = 0;
+ }
+
+ return mode_page_offset;
+}
+
+/**
+ * @brief This method will set the initial Mode Select processing state.
+ */
+static
+void sati_mode_select_initialize_mode_sel_processing_state(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 data_transfer_length,
+ U32 mode_page_offset
+ )
+{
+ sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0;
+ sequence->command_specific_data.process_state.mode_page_offset=mode_page_offset;
+ sequence->command_specific_data.process_state.mode_pages_size = data_transfer_length - mode_page_offset;
+ sequence->command_specific_data.process_state.size_of_data_processed = 0;
+ sequence->command_specific_data.process_state.current_mode_page_processed = FALSE;
+}
+
+/**
+ * @brief This method will get mode page size.
+ *
+ * @param[in] page_code This parameter contains page code for the current mode page.
+ *
+ * @return This method returns the size of current mode page.
+ */
+static
+U32 sati_mode_select_get_mode_page_size(
+ U8 page_code
+)
+{
+ U32 page_size=0;
+
+ switch (page_code)
+ {
+ case SCSI_MODE_PAGE_READ_WRITE_ERROR:
+ page_size=SCSI_MODE_PAGE_01_LENGTH;
+ break;
+
+ case SCSI_MODE_PAGE_DISCONNECT_RECONNECT:
+ page_size=SCSI_MODE_PAGE_02_LENGTH;
+ break;
+
+ case SCSI_MODE_PAGE_CACHING:
+ page_size=SCSI_MODE_PAGE_08_LENGTH;
+ break;
+
+ case SCSI_MODE_PAGE_CONTROL:
+ page_size=SCSI_MODE_PAGE_0A_LENGTH;
+ break;
+
+ case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL:
+ page_size=SCSI_MODE_PAGE_1C_LENGTH;
+ break;
+
+ case SCSI_MODE_PAGE_POWER_CONDITION:
+ page_size=SCSI_MODE_PAGE_1A_LENGTH;
+ break;
+ default:
+ page_size=0;
+ break;
+ }
+
+ return page_size;
+}
+
+/**
+ * @brief This method will check the validity of parameter data of Read Write Error Recovery
+ * page and further processing the page data if necessary.
+ *
+ * @param[in] page_size This parameter specifies page size of current mode page.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_mode_select_process_mode_page_read_write_error_recovery(
+ SATI_TRANSLATOR_SEQUENCE_T* sequence,
+ void * scsi_io,
+ U32 page_size
+ )
+{
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+ U8 current_mode_page[SCSI_MODE_PAGE_01_LENGTH]={0,0,0,0,0,0,0,0,0,0,0,0};
+ U32 mode_page_offset;
+
+ mode_page_offset = sequence->command_specific_data.process_state.mode_page_offset;
+
+ //Check all the defined bits for this page
+ //SPF(0b); Page length 0x0A;AWRE 1; ARRE 0; Error recovery bits 0; RC 0;
+ //Recovery time limit last two bytes 0
+
+ sati_get_data_byte(sequence, scsi_io, mode_page_offset, ¤t_mode_page[0]);
+ sati_get_data_byte(sequence, scsi_io, mode_page_offset+1, ¤t_mode_page[1]);
+ sati_get_data_byte(sequence, scsi_io, mode_page_offset+2, ¤t_mode_page[2]);
+ sati_get_data_byte(sequence, scsi_io, mode_page_offset+10, ¤t_mode_page[10]);
+ sati_get_data_byte(sequence, scsi_io, mode_page_offset+11, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_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, ¤t_mode_parameters[index]);
+ }
+
+ //medium type should be 0
+ if ( sati_mode_select_get_medium_type(current_mode_parameters, cdb_size) != 0 )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+ SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+ );
+ return status;
+ }
+
+ block_descriptor_length = sati_mode_select_get_mode_block_descriptor_length(
+ current_mode_parameters,
+ cdb_size
+ );
+
+ mode_page_offset = sati_mode_select_get_mode_page_offset(
+ block_descriptor_length,
+ cdb_size
+ );
+
+ if(mode_page_offset > data_transfer_length)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sati_mode_select_initialize_mode_sel_processing_state(
+ sequence,
+ scsi_io,
+ ata_io,
+ data_transfer_length,
+ mode_page_offset
+ );
+
+ }
+ }
+
+ // move to next mode page
+ if(sequence->command_specific_data.process_state.current_mode_page_processed)
+ {
+ sequence->command_specific_data.process_state.ata_command_sent_for_cmp = 0;
+ sequence->command_specific_data.process_state.current_mode_page_processed = FALSE;
+ }
+
+ status = sati_mode_select_process_mode_page(sequence, scsi_io, ata_io);
+
+ if(sequence->command_specific_data.process_state.current_mode_page_processed != FALSE)
+ {
+ // Done this page
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ }
+ else
+ {
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+
+ if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+ SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+ );
+ }
+
+ return status;
+}
+
+/**
+ * @brief This method will call Mode Select 6 Translation command
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ * successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the parameter data fields.
+ */
+SATI_STATUS sati_mode_select_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status=SATI_FAILURE;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ //PF bit needs to be 1 byte1 bit ???1????
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SELECT_PF_MASK) == !SCSI_MODE_SELECT_PF_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ return status;
+ }
+
+ status=sati_mode_select_translate_command(
+ sequence,
+ scsi_io,
+ ata_io,
+ 6
+ );
+
+ if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+ SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+ );
+ }
+ return status;
+
+}
+
+/**
+ * @brief This method will call Mode Select 10 translation command
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ * successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the parameter data fields.
+ */
+SATI_STATUS sati_mode_select_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status=SATI_FAILURE;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ //PF bit needs to be 1 byte1 bit ???1????
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SELECT_PF_MASK) == !SCSI_MODE_SELECT_PF_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ return status;
+ }
+
+ status=sati_mode_select_translate_command(
+ sequence,
+ scsi_io,
+ ata_io,
+ 10
+ );
+
+ if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+ SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+ );
+ }
+ return status;
+}
+
+/**
+* @brief This method will conduct error handling for the ATA Set Features command
+* that is issued during a Mode Select translation for the Caching Mode
+* page.
+*
+*
+* @return Indicate if the command translation succeeded.
+*
+* @retval SCI_COMPLETE This is returned if the command translation was
+* successful and no additional ATA commands need to be set.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+* sense data has been created as a result of an error returned
+*/
+SATI_STATUS sati_mode_select_translate_response(
+SATI_TRANSLATOR_SEQUENCE_T * sequence,
+void * scsi_io,
+void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ SATI_STATUS status = SATI_FAILURE;
+
+ if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ status = SATI_SEQUENCE_INCOMPLETE;
+ }
+ else
+ {
+ status = SATI_COMPLETE;
+ }
+ }
+ return status;
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SELECT)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_select.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_select.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,84 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SELECT_H_
+#define _SATI_MODE_SELECT_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI mode select (6 and 10-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_mode_select_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_mode_select_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_mode_select_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_MODE_SELECT_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,837 @@
+ /*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI mode sense (6 and 10-byte) commands.
+ */
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+
+#include <dev/isci/scil/sati_mode_sense.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+#define STANDBY_TIMER_DISABLED 0x00
+#define STANDBY_TIMER_ENABLED 0x01
+#define STANDBY_TIMER_SUPPORTED 0x2000
+
+
+
+/**
+ * @brief This method indicates if the supplied page control is supported
+ * by this translation implementation. Currently savable parameters
+ * (i.e. non-volatile) are not supported.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return This method returns an indication of whether the page control
+ * specified in the SCSI CDB is supported.
+ * @retval SATI_SUCCESS This value is returned if the page control is
+ * supported.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ * page control is not supported.
+ */
+static
+SATI_STATUS sati_mode_sense_is_page_control_supported(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ switch (sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT)
+ {
+ case SCSI_MODE_SENSE_PC_CURRENT:
+ case SCSI_MODE_SENSE_PC_DEFAULT:
+ case SCSI_MODE_SENSE_PC_CHANGEABLE:
+ return SATI_SUCCESS;
+ break;
+
+ default:
+ case SCSI_MODE_SENSE_PC_SAVED:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_SAVING_PARMS_NOT_SUPPORTED,
+ SCSI_ASCQ_SAVING_PARMS_NOT_SUPPORTED
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+}
+
+/**
+ * @brief This method indicates if the page code field in the SCSI CDB
+ * is supported by this translation.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] cdb_length This parameter specifies the length of the SCSI
+ * CDB being translated (e.g. 6-byte, 10-byte, 12-byte, etc.)
+ *
+ * @return This method returns an indication as to whether the page code
+ * in the CDB is supported.
+ * @retval SATI_SUCCESS This value is returned if the page code is
+ * supported.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ * page code is not supported.
+ */
+static
+SATI_STATUS sati_mode_sense_is_page_code_supported(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 cdb_length
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ switch (sati_get_cdb_byte(cdb, 2) & SCSI_MODE_SENSE_PAGE_CODE_ENABLE)
+ {
+ case SCSI_MODE_PAGE_CACHING:
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CACHING;
+ else
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CACHING;
+ break;
+
+ case SCSI_MODE_PAGE_ALL_PAGES:
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES;
+ else
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES;
+ break;
+
+ case SCSI_MODE_PAGE_READ_WRITE_ERROR:
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR;
+ else
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR;
+ break;
+
+ case SCSI_MODE_PAGE_DISCONNECT_RECONNECT:
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT;
+ else
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT;
+ break;
+
+ case SCSI_MODE_PAGE_CONTROL:
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_6_CONTROL;
+ else
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_10_CONTROL;
+ break;
+
+ case SCSI_MODE_PAGE_POWER_CONDITION:
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION;
+ else
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION;
+ break;
+
+ case SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL:
+ // The informational exceptions control page is only useful
+ // if SMART is supported.
+ if ((sequence->device->capabilities | SATI_DEVICE_CAP_SMART_SUPPORT)
+ == 0)
+ {
+ // For a MODE SENSE, utilize INVALID FIELD IN CDB,
+ // For a MODE SELECT, utilize INVALID FIELD IN PARAMETER LIST.
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_PARM_LIST,
+ SCSI_ASCQ_INVALID_FIELD_IN_PARM_LIST
+ );
+ }
+
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ if (sati_get_cdb_byte(cdb, 0) == SCSI_MODE_SENSE_6)
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL;
+ else
+ sequence->type = SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL;
+ break;
+
+ default:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+
+ return SATI_SUCCESS;
+}
+
+//******************************************************************************
+//* P R O T E C T E D M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will calculate the size of the mode sense data header.
+ * This includes the block descriptor if one is requested.
+ *
+ * @param[in] scsi_io This parameter specifies the user's SCSI IO object
+ * for which to calculate the mode page header.
+ * @param[in] cdb_size This parameter specifies the number of bytes
+ * associated with the CDB for which to calculate the header.
+ *
+ * @return This method returns the size, in bytes, for the mode page header.
+ */
+U16 sati_mode_sense_calculate_page_header(
+ void * scsi_io,
+ U8 cdb_size
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U16 page_length = 0;
+
+ // The Mode page header length is different for 6-byte vs. 10-byte CDBs.
+ if (cdb_size == 6)
+ page_length += SCSI_MODE_SENSE_6_HEADER_LENGTH;
+ else
+ page_length += SCSI_MODE_SENSE_10_HEADER_LENGTH;
+
+ // Are block descriptors disabled (DBD)? 0 indicates they are enabled.
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
+ {
+ // The LLBAA bit is not defined for 6-byte mode sense requests.
+ if ( (cdb_size == 10)
+ && (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE) )
+ page_length += SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH;
+ else
+ page_length += SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
+ }
+
+ return page_length;
+}
+
+/**
+ * @brief This method performs command translation common to all mode sense
+ * requests (6 or 10 byte).
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] cdb_length This parameter specifies the number of bytes
+ * in the CDB (6 or 10).
+ *
+ * @return This method returns an indication as to whether the translation
+ * succeeded.
+ * @retval SCI_SUCCESS This value is returned if translation succeeded.
+ * @see sati_mode_sense_is_page_control_supported() or
+ * sati_mode_sense_is_page_code_supported() for more information.
+ */
+SATI_STATUS sati_mode_sense_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 cdb_length
+)
+{
+ SATI_STATUS status;
+
+ /**
+ * Validate that the supplied page control (PC) field is supported.
+ */
+ status = sati_mode_sense_is_page_control_supported(sequence, scsi_io);
+ if (status != SATI_SUCCESS)
+ return status;
+
+ /**
+ * Validate that the supplied page code is supported.
+ */
+ status = sati_mode_sense_is_page_code_supported(sequence,scsi_io,cdb_length);
+ if (status != SATI_SUCCESS)
+ return status;
+
+ sati_ata_identify_device_construct(ata_io, sequence);
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will build the standard block descriptor for a MODE
+ * SENSE 6 or 10 byte request.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the IDENTIFY DEVICE data
+ * associated with the SCSI IO.
+ * @param[in] offset This parameter specifies the offset into the data
+ * buffer at which to build the block descriptor.
+ *
+ * @return This method returns the size of the block descriptor built.
+ */
+U32 sati_mode_sense_build_std_block_descriptor(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U32 lba_low = 0;
+ U32 lba_high = 0;
+ U32 sector_size = 0;
+
+ // Extract the sector information (sector size, logical blocks) from
+ // the retrieved ATA identify device data.
+ sati_ata_identify_device_get_sector_info(
+ identify, &lba_high, &lba_low, §or_size
+ );
+
+ // Fill in the 4-byte logical block address field.
+ sati_set_data_byte(sequence, scsi_io, offset, (U8)((lba_low>>24) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+1, (U8)((lba_low>>16) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+2, (U8)((lba_low>>8) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+3, (U8)(lba_low & 0xFF));
+
+ // Clear the reserved field.
+ sati_set_data_byte(sequence, scsi_io, offset+4, 0);
+
+ // Fill in the three byte Block Length field
+ sati_set_data_byte(sequence,scsi_io, offset+5, (U8)((sector_size>>16) & 0xFF));
+ sati_set_data_byte(sequence,scsi_io, offset+6, (U8)((sector_size>>8) & 0xFF));
+ sati_set_data_byte(sequence,scsi_io, offset+7, (U8)(sector_size & 0xFF));
+
+ return SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH;
+}
+
+/**
+ * @brief This method simply copies the mode sense data into the buffer
+ * at the location specified by page_start. The buffer copied is
+ * determined by page_control (e.g. current, default, or changeable
+ * values).
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] page_start This parameter specifies the starting offset at
+ * which to copy the mode page data.
+ * @param[in] page_control This parameter specifies the page control
+ * indicating the source buffer to be copied.
+ * @param[in] page_code This specifies the mode sense page to copy.
+ *
+ * @return This method returns the size of the mode page data being copied.
+ */
+U32 sati_mode_sense_copy_initial_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 page_start,
+ U8 page_control,
+ U8 page_code
+)
+{
+ U16 page_index = sati_mode_page_get_page_index(page_code);
+ U32 page_length = sat_mode_page_sizes[page_index];
+
+ // Find out if the current values are requested or if the default
+ // values are being requested.
+ if (page_control == SCSI_MODE_SENSE_PC_CHANGEABLE)
+ {
+ // Copy the changeable mode page information.
+ sati_copy_data(
+ sequence,
+ scsi_io,
+ page_start,
+ sat_changeable_mode_pages[page_index],
+ page_length
+ );
+ }
+ else
+ {
+ // Copy the default static values template to the user data area.
+ sati_copy_data(
+ sequence,
+ scsi_io,
+ page_start,
+ sat_default_mode_pages[page_index],
+ page_length
+ );
+ }
+
+ return page_length;
+}
+
+/**
+ * @brief This method performs the read/write error recovery mode page
+ * specific data translation based upon the contents of the remote
+ * device IDENTIFY DEVICE data.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ * IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ * buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ * translated.
+ */
+U32 sati_mode_sense_read_write_error_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+ U32 page_length;
+
+ page_length = sati_mode_sense_copy_initial_data(
+ sequence,
+ scsi_io,
+ offset,
+ page_control,
+ SCSI_MODE_PAGE_READ_WRITE_ERROR
+ );
+
+ // Currently we do not override any bits in this mode page from the
+ // identify data.
+
+ return page_length;
+}
+
+/**
+ * @brief This method performs the disconnect/reconnect mode page
+ * specific data translation based upon the contents of the remote
+ * device IDENTIFY DEVICE data.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ * IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ * buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ * translated.
+ */
+U32 sati_mode_sense_disconnect_reconnect_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+ U32 page_length;
+
+ page_length = sati_mode_sense_copy_initial_data(
+ sequence,
+ scsi_io,
+ offset,
+ page_control,
+ SCSI_MODE_PAGE_DISCONNECT_RECONNECT
+ );
+
+ // Currently we do not override any bits in this mode page from the
+ // identify data.
+
+ return page_length;
+}
+
+/**
+ * @brief This method performs the caching mode page specific data
+ * translation based upon the contents of the remote device IDENTIFY
+ * DEVICE data.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ * IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ * buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ * translated.
+ */
+U32 sati_mode_sense_caching_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+ U32 page_length;
+
+ page_length = sati_mode_sense_copy_initial_data(
+ sequence,
+ scsi_io,
+ offset,
+ page_control,
+ SCSI_MODE_PAGE_CACHING
+ );
+
+ // If the request queried for the current values, then
+ // we need to translate the data from the IDENTIFY DEVICE request.
+ if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
+ {
+ U8 value;
+
+ // Update the Write Cache Enabled (WCE) bit in the mode page data
+ // buffer based on the identify response.
+ if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_WCE_ENABLE) != 0)
+ {
+ sati_get_data_byte(sequence, scsi_io, offset+2, &value);
+ value |= SCSI_MODE_PAGE_CACHE_PAGE_WCE_BIT;
+ sati_set_data_byte(sequence, scsi_io, offset+2, value);
+ //This byte has been set twice and needs to be decremented
+ sequence->number_data_bytes_set--;
+ }
+
+ // Update the Disable Read Ahead (DRA) bit in the mode page data
+ // buffer based on the identify response.
+ if ((identify->command_set_enabled0 & ATA_IDENTIFY_DEVICE_RA_ENABLE) == 0)
+ {
+ // In SATA the polarity of the bits is inverse.
+ // - SCSI = Disable Read Ahead
+ // - ATA = Read Ahead
+ sati_get_data_byte(sequence, scsi_io, offset+12, &value);
+ value |= SCSI_MODE_PAGE_CACHE_PAGE_DRA_BIT;
+ sati_set_data_byte(sequence, scsi_io, offset+12, value);
+
+ //This byte has been set twice, the first time in
+ //sati_mode_sense_copy_initial_data. number_data_bytes_set
+ //needs to be decremented
+ sequence->number_data_bytes_set--;
+ }
+ }
+
+ return page_length;
+}
+
+/**
+ * @brief This method performs the control mode page specific data
+ * translation based upon the contents of the remote device
+ * IDENTIFY DEVICE data.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ * IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ * buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ * translated.
+ */
+U32 sati_mode_sense_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+ U32 page_length;
+ U8 value;
+
+ page_length = sati_mode_sense_copy_initial_data(
+ sequence,
+ scsi_io,
+ offset,
+ page_control,
+ SCSI_MODE_PAGE_CONTROL
+ );
+
+ if (sequence->device->descriptor_sense_enable)
+ {
+ sati_get_data_byte(sequence, scsi_io, offset+2,
+ &value);
+
+ sati_set_data_byte(sequence, scsi_io, offset+2,
+ value | SCSI_MODE_SELECT_MODE_PAGE_D_SENSE);
+ }
+
+ return page_length;
+}
+
+/**
+ * @brief This method performs the informational exceptions control mode
+ * page specific data translation based upon the contents of the
+ * remote device IDENTIFY DEVICE data.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ * IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ * buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ * translated.
+ */
+U32 sati_mode_sense_informational_excp_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+ U32 page_length;
+
+ page_length = sati_mode_sense_copy_initial_data(
+ sequence,
+ scsi_io,
+ offset,
+ page_control,
+ SCSI_MODE_PAGE_INFORMATIONAL_EXCP_CONTROL
+ );
+
+ // If the request queried for the current values, then
+ // we need to translate the data from the IDENTIFY DEVICE request.
+ if (page_control == SCSI_MODE_SENSE_PC_CURRENT)
+ {
+ U8 value;
+
+ sati_get_data_byte(sequence, scsi_io, offset+2, &value);
+
+ // Determine if the SMART feature set is supported and enabled.
+ if ( (identify->command_set_supported0
+ & ATA_IDENTIFY_COMMAND_SET_SUPPORTED0_SMART_ENABLE)
+ && (identify->command_set_enabled0
+ & ATA_IDENTIFY_COMMAND_SET_ENABLED0_SMART_ENABLE) )
+ {
+ // Clear the DXCPT field since the SMART feature is supported/enabled.
+ value &= ~SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
+ }
+ else
+ {
+ // Set the Disable Exception Control (DXCPT) field since the SMART
+ // feature is not supported or enabled.
+ value |= SCSI_MODE_PAGE_INFORMATIONAL_EXCP_DXCPT_ENABLE;
+ }
+
+ sati_set_data_byte(sequence, scsi_io, offset+2, value);
+
+ //This byte has been set twice, the first time in
+ //sati_mode_sense_copy_initial_data. number_data_bytes_set
+ //needs to be decremented
+ sequence->number_data_bytes_set--;
+ }
+
+ return page_length;
+}
+
+/**
+* @brief This method performs the Power Condition mode page
+* specific data translation based upon the contents of the
+* remote device IDENTIFY DEVICE data.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_command().
+*
+* @param[in] identify This parameter specifies the remote device's
+* IDENTIFY DEVICE data received as part of the IO request.
+* @param[in] offset This parameter specifies the offset into the data
+* buffer where the translated data is to be written.
+*
+* @return This method returns the size of the mode page data that was
+* translated.
+*/
+U32 sati_mode_sense_power_condition_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 page_control = sati_get_cdb_byte(cdb, 2) >> SCSI_MODE_SENSE_PC_SHIFT;
+
+ U8 ata_sb_timer;
+
+ //Represents tenths of seconds
+ U32 standby_timer = 0x00000000;
+
+ U8 standby_enabled = STANDBY_TIMER_DISABLED;
+
+ if ((page_control == SCSI_MODE_SENSE_PC_CURRENT) &&
+ (identify->capabilities1 & STANDBY_TIMER_SUPPORTED))
+ {
+ standby_enabled = STANDBY_TIMER_ENABLED;
+
+ ata_sb_timer = sequence->device->ata_standby_timer;
+
+ //converting ATA timer values into SCSI timer values
+ if(ata_sb_timer <= 0xF0)
+ {
+ standby_timer = ata_sb_timer * 50;
+ }
+ else if(ata_sb_timer <= 0xFB)
+ {
+ standby_timer = ((ata_sb_timer - 240) * 18000);
+ }
+ else if(ata_sb_timer == 0xFC)
+ {
+ standby_timer = 12600;
+ }
+ else if(ata_sb_timer == 0xFD)
+ {
+ standby_timer = 432000;
+ }
+ else if(ata_sb_timer == 0xFF)
+ {
+ standby_timer = 12750;
+ }
+ else
+ {
+ standby_timer = 0xFFFFFFFF;
+ }
+ }
+
+ sati_set_data_byte(sequence, scsi_io, offset, SCSI_MODE_PAGE_POWER_CONDITION);
+ sati_set_data_byte(sequence, scsi_io, offset + 1, (SCSI_MODE_PAGE_1A_LENGTH - 2));
+ sati_set_data_byte(sequence, scsi_io, offset + 2, 0x00);
+ sati_set_data_byte(sequence, scsi_io, offset + 3, standby_enabled);
+ sati_set_data_byte(sequence, scsi_io, offset + 4, 0x00);
+ sati_set_data_byte(sequence, scsi_io, offset + 5, 0x00);
+ sati_set_data_byte(sequence, scsi_io, offset + 6, 0x00);
+ sati_set_data_byte(sequence, scsi_io, offset + 7, 0x00);
+ sati_set_data_byte(sequence, scsi_io, offset + 8, (U8) (standby_timer >> 24));
+ sati_set_data_byte(sequence, scsi_io, offset + 9, (U8) (standby_timer >> 16));
+ sati_set_data_byte(sequence, scsi_io, offset + 10, (U8) (standby_timer >> 8));
+ sati_set_data_byte(sequence, scsi_io, offset + 11, (U8) standby_timer);
+
+ return SCSI_MODE_PAGE_1A_LENGTH;
+}
+
+/**
+ * @brief This method performs the all pages mode page specific data
+ * translation based upon the contents of the remote device
+ * IDENTIFY DEVICE data. The ALL PAGES mode sense request asks
+ * for all of mode pages and sub-pages in a single page.
+ * The mode pages are added in ascending order.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's
+ * IDENTIFY DEVICE data received as part of the IO request.
+ * @param[in] offset This parameter specifies the offset into the data
+ * buffer where the translated data is to be written.
+ *
+ * @return This method returns the size of the mode page data that was
+ * translated.
+ */
+U32 sati_mode_sense_all_pages_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ offset += sati_mode_sense_read_write_error_translate_data(
+ sequence, scsi_io, identify, offset
+ );
+
+ offset += sati_mode_sense_disconnect_reconnect_translate_data(
+ sequence, scsi_io, identify, offset
+ );
+
+ offset += sati_mode_sense_caching_translate_data(
+ sequence, scsi_io, identify, offset
+ );
+
+ offset += sati_mode_sense_control_translate_data(
+ sequence, scsi_io, identify, offset
+ );
+
+ offset += sati_mode_sense_informational_excp_control_translate_data(
+ sequence, scsi_io, identify, offset
+ );
+
+ return offset;
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,146 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SENSE_H_
+#define _SATI_MODE_SENSE_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type defintions
+ * common to translations of the SCSI mode sense (6 and 10-byte)
+ * commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/intel_ata.h>
+
+U16 sati_mode_sense_calculate_page_header(
+ void * scsi_io,
+ U8 cdb_size
+);
+
+SATI_STATUS sati_mode_sense_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 cdb_length
+);
+
+U32 sati_mode_sense_build_std_block_descriptor(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+U32 sati_mode_sense_copy_initial_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 page_start,
+ U8 page_control,
+ U8 page_code
+);
+
+U32 sati_mode_sense_caching_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+U32 sati_mode_sense_informational_excp_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+U32 sati_mode_sense_all_pages_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+U32 sati_mode_sense_read_write_error_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+U32 sati_mode_sense_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+U32 sati_mode_sense_disconnect_reconnect_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+U32 sati_mode_sense_power_condition_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+);
+
+
+#endif // _SATI_MODE_SENSE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_10.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_10.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,509 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI mode sense 10-byte commands.
+ */
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+
+#include <dev/isci/scil/sati_mode_sense.h>
+#include <dev/isci/scil/sati_mode_sense_10.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method builds the mode parameter header for a 10-byte SCSI
+ * mode sense data response. The parameter header is 4 bytes in
+ * size.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the ATA remote device's
+ * received IDENTIFY DEVICE data.
+ * @param[in] mode_data_length This parameter specifies the amount of data
+ * to be returned as part of this mode sense request.
+ *
+ * @return This method returns the number of bytes written into the
+ * mode sense data buffer.
+ */
+static
+U32 sati_mode_sense_10_build_header(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U16 mode_data_length
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ // Fill in the length of the mode parameter data returned (do not include
+ // the size of the mode data length field in the total). Adjust the
+ // mode data length to not include the mode data length fields itself
+ // (i.e. subtract 2).
+ mode_data_length -= 2;
+ sati_set_data_byte(sequence, scsi_io, 0, (U8)(mode_data_length >> 8) & 0xFF);
+ sati_set_data_byte(sequence, scsi_io, 1, (U8)(mode_data_length & 0xFF));
+
+ // Medium Type is 0 for SBC devices
+ sati_set_data_byte(sequence, scsi_io, 2, SCSI_MODE_HEADER_MEDIUM_TYPE_SBC);
+
+ // Write Protect (WP), Rsvd, DPOFUA, Rsvd
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_DMA_FUA_ENABLE)
+ sati_set_data_byte(sequence,scsi_io,3,SCSI_MODE_SENSE_HEADER_FUA_ENABLE);
+ else
+ sati_set_data_byte(sequence, scsi_io, 3, 0);
+
+ // Set the reserved bytes to 0. The LONGLBA field in byte 4 is overridden
+ // later in this method if LLBAA is enabled.
+ sati_set_data_byte(sequence, scsi_io, 4, 0);
+ sati_set_data_byte(sequence, scsi_io, 5, 0);
+
+ // The MSB for the block descriptor length is never used since the
+ // largest block descriptor in this translator is 16-bytes in size.
+ sati_set_data_byte(sequence, scsi_io, 6, 0);
+
+ // Set the LSB block descriptor length if block descriptors are utilized.
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE)
+ sati_set_data_byte(sequence, scsi_io, 7, 0);
+ else
+ {
+ // If Long Logical Block Address are allowed, then the block descriptor
+ // is larger (16 bytes total).
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE)
+ {
+ sati_set_data_byte(sequence, scsi_io, 4, 1);
+ sati_set_data_byte(
+ sequence, scsi_io, 7, SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH
+ );
+ }
+ else
+ {
+ sati_set_data_byte(
+ sequence, scsi_io, 7, SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH
+ );
+ }
+ }
+
+ return SCSI_MODE_SENSE_10_HEADER_LENGTH;
+}
+
+static
+U32 sati_mode_sense_10_build_llba_block_descriptor(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 offset
+)
+{
+ U32 lba_low = 0;
+ U32 lba_high = 0;
+ U32 sector_size = 0;
+
+ // Extract the sector information (sector size, logical blocks) from
+ // the retrieved ATA identify device data.
+ sati_ata_identify_device_get_sector_info(
+ identify, &lba_low, &lba_high, §or_size
+ );
+
+ // Fill in the 8-byte logical block area
+ sati_set_data_byte(sequence, scsi_io, offset, (U8)((lba_high>>24) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+1, (U8)((lba_high>>16) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+2, (U8)((lba_high>>8) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+3, (U8)(lba_high & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+4, (U8)((lba_low>>24) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+5, (U8)((lba_low>>16) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+6, (U8)((lba_low>>8) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, offset+7, (U8)(lba_low & 0xFF));
+
+ // Clear the reserved fields.
+ sati_set_data_byte(sequence, scsi_io, offset+8, 0);
+ sati_set_data_byte(sequence, scsi_io, offset+9, 0);
+ sati_set_data_byte(sequence, scsi_io, offset+10, 0);
+ sati_set_data_byte(sequence, scsi_io, offset+11, 0);
+
+ // Fill in the four byte Block Length field
+ sati_set_data_byte(sequence,scsi_io, offset+12, (U8)((sector_size>>24) & 0xFF));
+ sati_set_data_byte(sequence,scsi_io, offset+13, (U8)((sector_size>>16) & 0xFF));
+ sati_set_data_byte(sequence,scsi_io, offset+14, (U8)((sector_size>>8) & 0xFF));
+ sati_set_data_byte(sequence,scsi_io, offset+15, (U8)(sector_size & 0xFF));
+
+ return SCSI_MODE_SENSE_LLBA_BLOCK_DESCRIPTOR_LENGTH;
+}
+
+/**
+ * @brief This method perform the data translation common to all SCSI MODE
+ * SENSE 10 byte commands. This includes building the mode page
+ * header and block descriptor (if requested).
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's IDENTIFY
+ * DEVICE data to be used during translation.
+ * @param[in] transfer_length This parameter specifies the size of the
+ * mode page (including header & block descriptor).
+ *
+ * @return This method returns the number of bytes written into the user's
+ * mode page data buffer.
+ */
+static
+U32 sati_mode_sense_10_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ void * scsi_io,
+ U16 transfer_length
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 offset;
+
+ offset = sati_mode_sense_10_build_header(
+ sequence, scsi_io, identify, transfer_length
+ );
+
+ // Determine if the caller disabled block descriptors (DBD). If not,
+ // then generate a block descriptor.
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
+ {
+ // If the user requested the Long LBA format descriptor, then build
+ // it
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_LLBAA_ENABLE)
+ offset += sati_mode_sense_10_build_llba_block_descriptor(
+ sequence, scsi_io, identify, offset
+ );
+ else
+ offset += sati_mode_sense_build_std_block_descriptor(
+ sequence, scsi_io, identify, offset
+ );
+ }
+
+ return offset;
+}
+
+//******************************************************************************
+//* P R O T E C T E D M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI mode sense 6 byte command
+ * into corresponding ATA commands. If the command is well-formed,
+ * then the translation will result in an ATA IDENTIFY DEVICE
+ * command.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the CDB.
+ */
+SATI_STATUS sati_mode_sense_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ sequence->command_specific_data.scratch = 0;
+
+ // Set the data length based on the allocation length field in the CDB.
+ sequence->allocation_length = (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8));
+
+ return sati_mode_sense_translate_command(sequence, scsi_io, ata_io, 10);
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ * input data (i.e. an ATA IDENTIFY DEVICE block) into a CACHING
+ * mode page format. The data will be written into the user's mode
+ * page data buffer. This function operates specifically for MODE
+ * SENSE 10 commands.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_10_caching_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U16 data_length = sati_mode_sense_calculate_page_header(scsi_io, 10)
+ + SCSI_MODE_PAGE_08_LENGTH;
+ U32 page_offset = sati_mode_sense_10_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_caching_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ * input data (i.e. an ATA IDENTIFY DEVICE block) into a INFORMATIONAL
+ * EXCEPTIONS CONTROL mode page format. The data will be written
+ * into the user's mode page data buffer. This function operates
+ * specifically for MODE SENSE 10 commands.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_10_informational_excp_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U16 data_length = sati_mode_sense_calculate_page_header(scsi_io, 10)
+ + SCSI_MODE_PAGE_1C_LENGTH;
+ U32 page_offset = sati_mode_sense_10_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_informational_excp_control_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a Read Write Error
+* mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 10 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_read_write_error_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U16 data_length = sati_mode_sense_calculate_page_header(scsi_io, 10)
+ + SCSI_MODE_PAGE_01_LENGTH;
+
+ U32 page_offset = sati_mode_sense_10_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_read_write_error_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a Disconnect
+* Reconnect mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 10 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_disconnect_reconnect_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+ + SCSI_MODE_PAGE_02_LENGTH;
+
+ U32 page_offset = sati_mode_sense_10_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_disconnect_reconnect_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a Control
+* mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 10 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+ + SCSI_MODE_PAGE_0A_LENGTH;
+
+ U32 page_offset = sati_mode_sense_10_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_control_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a Power
+* Condition mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 10 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_10_power_condition_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U8 data_length;
+ U32 page_offset;
+
+ data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+ + SCSI_MODE_PAGE_1A_LENGTH;
+
+ page_offset = sati_mode_sense_10_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_power_condition_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ * input data (i.e. an ATA IDENTIFY DEVICE block) into an ALL
+ * PAGES mode page format. The ALL PAGES mode page is basically a
+ * conglomeration of all mode pages and sub-pages into a single
+ * page. The data will be written into the user's mode page
+ * data buffer. This function operates specifically for MODE
+ * SENSE 10 commands.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_10_all_pages_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 10)
+ + SCSI_MODE_PAGE_01_LENGTH
+ + SCSI_MODE_PAGE_02_LENGTH
+ + SCSI_MODE_PAGE_08_LENGTH
+ + SCSI_MODE_PAGE_0A_LENGTH
+ + SCSI_MODE_PAGE_1C_LENGTH;
+ U32 page_offset = sati_mode_sense_10_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_all_pages_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_10.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_10.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,114 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SENSE_10_H_
+#define _SATI_MODE_SENSE_10_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes required to
+ * translate the SCSI mode sense 10-byte commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_mode_sense_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+void sati_mode_sense_10_caching_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_10_informational_excp_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_10_read_write_error_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_10_disconnect_reconnect_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_10_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_10_power_condition_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_10_all_pages_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+#endif // _SATI_MODE_SENSE_10_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_6.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_6.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,429 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI mode sense 6-byte commands.
+ */
+
+#if !defined(DISABLE_SATI_MODE_SENSE)
+
+#include <dev/isci/scil/sati_mode_sense.h>
+#include <dev/isci/scil/sati_mode_sense_6.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method builds the mode parameter header for a 6-byte SCSI
+ * mode sense data response. The parameter header is 4 bytes in
+ * size.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the ATA remote device's
+ * received IDENTIFY DEVICE data.
+ * @param[in] mode_data_length This parameter specifies the amount of data
+ * to be returned as part of this mode sense request.
+ *
+ * @return This method returns the number of bytes written into the
+ * data buffer.
+ */
+static
+U32 sati_mode_sense_6_build_header(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U8 mode_data_length
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ // Fill in the length of the mode parameter data returned (do not include
+ // the size of the mode data length field in the total).
+ sati_set_data_byte(sequence, scsi_io, 0, (U8)mode_data_length-1);
+
+ // Medium Type is 0 for SBC devices
+ sati_set_data_byte(sequence, scsi_io, 1, SCSI_MODE_HEADER_MEDIUM_TYPE_SBC);
+
+ // Write Protect (WP), Rsvd, DPOFUA, Rsvd
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_DMA_FUA_ENABLE)
+ sati_set_data_byte(sequence,scsi_io,2,SCSI_MODE_SENSE_HEADER_FUA_ENABLE);
+ else
+ sati_set_data_byte(sequence, scsi_io, 2, 0);
+
+ // Set the block descriptor length if block descriptors are utilized.
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE)
+ sati_set_data_byte(sequence, scsi_io, 3, 0);
+ else
+ sati_set_data_byte(
+ sequence, scsi_io, 3, SCSI_MODE_SENSE_STD_BLOCK_DESCRIPTOR_LENGTH
+ );
+
+ return SCSI_MODE_SENSE_6_HEADER_LENGTH;
+}
+
+/**
+ * @brief This method perform the data translation common to all SCSI MODE
+ * SENSE 6 byte commands. This includes building the mode page
+ * header and block descriptor (if requested).
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] identify This parameter specifies the remote device's IDENTIFY
+ * DEVICE data to be used during translation.
+ * @param[in] transfer_length This parameter specifies the size of the
+ * mode page (including header & block descriptor).
+ *
+ * @return This method returns the number of bytes written into the user's
+ * mode page data buffer.
+ */
+static
+U32 sati_mode_sense_6_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ void * scsi_io,
+ U8 transfer_length
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 offset;
+
+ offset = sati_mode_sense_6_build_header(
+ sequence, scsi_io, identify, transfer_length
+ );
+
+ // Determine if the caller disabled block descriptors (DBD). If not,
+ // then generate a block descriptor.
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_MODE_SENSE_DBD_ENABLE) == 0)
+ offset += sati_mode_sense_build_std_block_descriptor(
+ sequence, scsi_io, identify, offset
+ );
+
+ return offset;
+}
+
+//******************************************************************************
+//* P R O T E C T E D M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI mode sense 6 byte command
+ * into corresponding ATA commands. If the command is well-formed,
+ * then the translation will result in an ATA IDENTIFY DEVICE
+ * command.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the CDB.
+ */
+SATI_STATUS sati_mode_sense_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ // Set the data length based on the allocation length field in the CDB.
+ sequence->allocation_length = sati_get_cdb_byte(cdb, 4);
+
+ return sati_mode_sense_translate_command(sequence, scsi_io, ata_io, 6);
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ * input data (i.e. an ATA IDENTIFY DEVICE block) into a CACHING
+ * mode page format. The data will be written into the user's mode
+ * page data buffer. This function operates specifically for MODE
+ * SENSE 6 commands.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_6_caching_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+ + SCSI_MODE_PAGE_08_LENGTH;
+ U32 page_offset = sati_mode_sense_6_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_caching_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ * input data (i.e. an ATA IDENTIFY DEVICE block) into a INFORMATIONAL
+ * EXCEPTIONS CONTROL mode page format. The data will be written
+ * into the user's mode page data buffer. This function operates
+ * specifically for MODE SENSE 6 commands.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_6_informational_excp_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+ + SCSI_MODE_PAGE_1C_LENGTH;
+ U32 page_offset = sati_mode_sense_6_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_informational_excp_control_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a DISCONNECT
+* RECONNECT mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 6 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_disconnect_reconnect_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+ + SCSI_MODE_PAGE_02_LENGTH ;
+
+ U32 page_offset = sati_mode_sense_6_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_disconnect_reconnect_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a READ WRITE ERROR
+* mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 6 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_read_write_error_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+ + SCSI_MODE_PAGE_01_LENGTH;
+
+ U32 page_offset = sati_mode_sense_6_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_read_write_error_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a CONTROL
+* mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 6 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+ + SCSI_MODE_PAGE_0A_LENGTH;
+
+ U32 page_offset = sati_mode_sense_6_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_control_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+/**
+* @brief This method will perform data translation from the supplied ATA
+* input data (i.e. an ATA IDENTIFY DEVICE block) into a Power
+* Condition mode page format. The data will be written
+* into the user's mode page data buffer. This function operates
+* specifically for MODE SENSE 6 commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_data().
+*
+* @return none.
+*/
+void sati_mode_sense_6_power_condition_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+
+ U8 data_length;
+ U32 page_offset;
+
+ data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+ + SCSI_MODE_PAGE_1A_LENGTH;
+
+ page_offset = sati_mode_sense_6_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_power_condition_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+
+
+/**
+ * @brief This method will perform data translation from the supplied ATA
+ * input data (i.e. an ATA IDENTIFY DEVICE block) into an ALL
+ * PAGES mode page format. The ALL PAGES mode page is basically a
+ * conglomeration of all mode pages and sub-pages into a single
+ * page. The data will be written into the user's mode page
+ * data buffer. This function operates specifically for MODE
+ * SENSE 6 commands.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_data().
+ *
+ * @return none.
+ */
+void sati_mode_sense_6_all_pages_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ ATA_IDENTIFY_DEVICE_DATA_T * identify = (ATA_IDENTIFY_DEVICE_DATA_T*)
+ ata_input_data;
+ U8 data_length = (U8) sati_mode_sense_calculate_page_header(scsi_io, 6)
+ + SCSI_MODE_PAGE_01_LENGTH
+ + SCSI_MODE_PAGE_02_LENGTH
+ + SCSI_MODE_PAGE_08_LENGTH
+ + SCSI_MODE_PAGE_0A_LENGTH
+ + SCSI_MODE_PAGE_1C_LENGTH;
+
+ U32 page_offset = sati_mode_sense_6_translate_data(
+ sequence, identify, scsi_io, data_length
+ );
+
+ sati_mode_sense_all_pages_translate_data(
+ sequence, scsi_io, identify, page_offset
+ );
+}
+
+#endif // !defined(DISABLE_SATI_MODE_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_mode_sense_6.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_mode_sense_6.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,114 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MODE_SENSE_6_H_
+#define _SATI_MODE_SENSE_6_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes required to
+ * translate the SCSI mode sense 6-byte commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_mode_sense_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+void sati_mode_sense_6_caching_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_6_informational_excp_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_6_read_write_error_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_6_disconnect_reconnect_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_6_control_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_6_power_condition_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_mode_sense_6_all_pages_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+#endif // _SATI_MODE_SENSE_6_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_move.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_move.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,616 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations common to
+ * translations that move data (i.e. read, write). It has code for
+ * the various different size CDBs (6, 10, 12, 16).
+ */
+
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method simply sets the command register based upon the
+ * supplied opcodes and the data direction.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command()
+ *
+ * @param[in] write_opcode This parameter specifies the value to be written
+ * to the ATA command register for a write (data out) operation.
+ * @param[in] read_opcode This parameter specifies the value to be written
+ * to the ATA command register for a read (data in) operation.
+ *
+ * @return none.
+ */
+static
+void sati_move_set_ata_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_io,
+ U8 write_opcode,
+ U8 read_opcode
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ if (sequence->data_direction == SATI_DATA_DIRECTION_OUT)
+ sati_set_ata_command(register_fis, write_opcode);
+ else
+ sati_set_ata_command(register_fis, read_opcode);
+}
+
+/**
+ * @brief This method will translate the SCSI transfer count from the 6-byte
+ * CDB into the appropriate amount in the ATA register FIS. Please
+ * note for 48-bit UDMA requests, the caller must set the sector
+ * count extended field. This method also sets protocol and
+ * command fields.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command()
+ *
+ * @param[in] write_opcode This parameter specifies the value to be written
+ * to the ATA command register for a write (data out) operation.
+ * @param[in] read_opcode This parameter specifies the value to be written
+ * to the ATA command register for a read (data in) operation.
+ *
+ * @return none
+ */
+static
+void sati_move_small_udma_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 write_opcode,
+ U8 read_opcode
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_move_set_ata_command(sequence, ata_io, write_opcode, read_opcode);
+ sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 4));
+
+ if (sequence->data_direction == SATI_DATA_DIRECTION_IN)
+ sequence->protocol = SAT_PROTOCOL_UDMA_DATA_IN;
+ else
+ sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT;
+}
+
+/**
+ * @brief This method will translate the SCSI transfer count from the
+ * supplied sector_count parameter into the ATA register FIS.
+ * The translation is specific to 10,12, 16 byte CDBs.
+ * This method also sets protocol and command fields.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command()
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ * to be transfered.
+ * @param[in] write_opcode This parameter specifies the value to be written
+ * to the ATA command register for a write (data out) operation.
+ * @param[in] read_opcode This parameter specifies the value to be written
+ * to the ATA command register for a read (data in) operation.
+ *
+ * @return Please reference sati_move_set_sector_count() for information
+ * on return codes from this method.
+ */
+static
+SATI_STATUS sati_move_large_udma_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 write_opcode,
+ U8 read_opcode
+)
+{
+ sati_move_set_ata_command(sequence, ata_io, write_opcode, read_opcode);
+
+ if (sequence->data_direction == SATI_DATA_DIRECTION_IN)
+ sequence->protocol = SAT_PROTOCOL_UDMA_DATA_IN;
+ else
+ sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT;
+
+ return sati_move_set_sector_count(
+ sequence, scsi_io, ata_io, sector_count, FALSE
+ );
+}
+
+/**
+ * @brief This method will translate the SCSI transfer count from the 6-byte
+ * CDB into the appropriate amount in the ATA register FIS.
+ * This is only used for translation of 6-byte SCSI CDBs.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command()
+ *
+ * @return none
+ */
+static
+void sati_move_ncq_translate_8_bit_sector_count(
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 4));
+
+ // A read 6 with a 0 sector count indicates a transfer of 256 sectors.
+ // As a result update the MSB (features expanded register) to indicate
+ // 256 sectors (0x100).
+ if (sati_get_cdb_byte(cdb, 4) == 0)
+ sati_set_ata_features_exp(register_fis, 1);
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will process a 32-bit sector into the appropriate fields
+ * in a register FIS. This method works for both 8-bit and 16-bit sector
+ * counts.
+ * This is used for translation of 10, 12, and 16-byte SCSI CDBs.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @note This method should only be called for CDB sizes of 10-bytes or larger.
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ * to be transfered.
+ * @param[in] is_fpdma_command This parameter indicates if the supplied
+ * ata_io is a first party DMA request (NCQ).
+ *
+ * @return none
+ */
+SATI_STATUS sati_move_set_sector_count(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 is_fpdma_command
+)
+{
+ U32 max_sector_count;
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+ max_sector_count = 65536;
+ else
+ max_sector_count = 256;
+
+ // Check the CDB transfer length count and set the register FIS sector
+ // count fields
+ if (0 == sector_count)
+ {
+ // A SCSI sector count of 0 for 10-byte CDBs and larger indicate no data
+ // transfer, so simply complete the command immediately.
+ return SATI_COMPLETE;
+ }
+ else if (sector_count >= max_sector_count)
+ {
+ // We have to perform multiple SATA commands to satisfy the sector
+ // count specified in the SCSI command.
+ sequence->command_specific_data.move_sector_count =
+ sector_count - max_sector_count;
+
+ // In ATA a sector count of 0 indicates use the maximum allowed for
+ // the command (i.e. 0 == 2^16 or 2^8).
+ sector_count = 0;
+ }
+
+ if (is_fpdma_command)
+ {
+ sati_set_ata_features(register_fis, sector_count & 0xFF);
+ sati_set_ata_features_exp(register_fis, (sector_count >> 8) & 0xFF);
+ }
+ else
+ {
+ sati_set_ata_sector_count(register_fis, sector_count & 0xFF);
+ sati_set_ata_sector_count_exp(register_fis, (sector_count >> 8) & 0xFF);
+ }
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method simply translates the 32-bit logical block address
+ * field from the SCSI CDB (10 or 12-byte) into the ATA task
+ * file (register FIS).
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command()
+ *
+ * @return none
+ */
+void sati_move_translate_32_bit_lba(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 5));
+ sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 4));
+ sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 3));
+ sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 2));
+ sati_set_ata_lba_mid_exp(register_fis, 0);
+ sati_set_ata_lba_high_exp(register_fis, 0);
+}
+
+/**
+ * @brief This method simply translates the 64-bit logical block address
+ * field from the SCSI CDB (16 byte) into the ATA task
+ * file (register FIS). The 2 most significant bytes must be 0,
+ * since ATA devices can, at most, support 48-bits of LBA.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command()
+ *
+ * @return Indicate if the LBA translation succeeded.
+ * @return SATI_SUCCESS This is returned if translation was successful.
+ * @return SATI_FAILURE_CHECK_RESPONSE_DATA This is returned if either
+ * of the 2 most significant bytes contain a non-zero value.
+ */
+SATI_STATUS sati_move_translate_64_bit_lba(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ // Ensure we receive a logical block address that is within range of
+ // addressibility per the ATA specification (i.e. 48-bit or 28-bit).
+ if ( (sati_get_cdb_byte(cdb, 2) == 0) && (sati_get_cdb_byte(cdb, 3) == 0) )
+ {
+ sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 9));
+ sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 8));
+ sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 7));
+ sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 6));
+ sati_set_ata_lba_mid_exp(register_fis, sati_get_cdb_byte(cdb, 5));
+ sati_set_ata_lba_high_exp(register_fis, sati_get_cdb_byte(cdb, 4));
+ return SATI_SUCCESS;
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_LBA_OUT_OF_RANGE,
+ SCSI_ASCQ_LBA_OUT_OF_RANGE
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+}
+
+/**
+ * @brief This method will translate the pieces common to SCSI read and
+ * write 6 byte commands. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ */
+SATI_STATUS sati_move_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ // Translate the logical block address information from the SCSI CDB.
+ // There is only 5 bits of MSB located in byte 1 of the CDB.
+ sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 3));
+ sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 2));
+ sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 1) & 0x1F);
+
+ sati_move_translate_command(sequence, scsi_io, ata_io, 0);
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the pieces common to SCSI read and
+ * write 10/12 byte commands. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] device_head This parameter specifies the contents to be
+ * written to the device head register.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ */
+SATI_STATUS sati_move_32_bit_lba_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 device_head
+)
+{
+ sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+ sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method provides the common translation functionality for
+ * the 6-byte move command descriptor blocks (CDBs).
+ * This method will ensure that the following is performed:
+ * - command register is set
+ * - the SATI_TRANSLATOR_SEQUENCE::protocol field is set
+ * - the sector count field(s) are set
+ * - sati_move_6_translate_command() is invoked.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @pre The caller must ensure that the
+ * SATI_TRANSLATOR_SEQUENCE::data_direction field has already been set.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_6_translate_command() for additional return codes.
+ */
+SATI_STATUS sati_move_small_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ // Translation of the sector count is performed differently for NCQ vs.
+ // other protocols.
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE)
+ {
+ sati_move_set_ata_command(
+ sequence, ata_io, ATA_WRITE_FPDMA, ATA_READ_FPDMA
+ );
+ sati_move_ncq_translate_8_bit_sector_count(scsi_io, ata_io);
+ sequence->protocol = SAT_PROTOCOL_FPDMA;
+ }
+ else if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+ {
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ sati_move_small_udma_translate_command(
+ sequence, scsi_io, ata_io, ATA_WRITE_DMA_EXT, ATA_READ_DMA_EXT
+ );
+
+ // A read/write 6 with a 0 sector count indicates a transfer of 256
+ // sectors. As a result update the MSB (features expanded register)
+ // to indicate 256 sectors (0x100).
+ if (sati_get_cdb_byte(cdb, 4) == 0)
+ {
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+ sati_set_ata_sector_count_exp(register_fis, 1);
+ }
+ }
+ else if (sequence->device->capabilities & SATI_DEVICE_CAP_UDMA_ENABLE)
+ {
+ sati_move_small_udma_translate_command(
+ sequence, scsi_io, ata_io, ATA_WRITE_DMA, ATA_READ_DMA
+ );
+ }
+ else
+ {
+ /**
+ * Currently the translation does not support devices incapable of
+ * handling the 48-bit feature set (i.e. 16 bits of sector count).
+ */
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ return sati_move_6_translate_command(sequence, scsi_io, ata_io);
+}
+
+/**
+ * @brief This method provides the common translation functionality for
+ * the larger command descriptor blocks (10, 12, 16-byte CDBs).
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ * to be transfered.
+ * @param[in] device_head This parameter specifies the contents to be
+ * written to the device head register.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_FAILURE This value is returned if neither NCQ or DMA is
+ * supported by the target device.
+ * @see sati_move_set_sector_count() for additional return codes.
+ */
+SATI_STATUS sati_move_large_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 * ata_device_head
+)
+{
+ SATI_STATUS status = SATI_SUCCESS;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ // Parts of translation (e.g. sector count) is performed differently
+ // for NCQ vs. other protocols.
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_NCQ_SUPPORTED_ENABLE)
+ {
+ // if the user did not request to ignore FUA
+ if((sequence->device->capabilities & SATI_DEVICE_CAP_IGNORE_FUA)==0)
+ {
+ // Is the Force Unit Access bit set?
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_MOVE_FUA_BIT_ENABLE)
+ *ata_device_head = ATA_DEV_HEAD_REG_FUA_ENABLE;
+ }
+
+ sati_move_set_ata_command(
+ sequence, ata_io, ATA_WRITE_FPDMA, ATA_READ_FPDMA
+ );
+ status = sati_move_set_sector_count(
+ sequence, scsi_io, ata_io, sector_count, TRUE
+ );
+ sequence->protocol = SAT_PROTOCOL_FPDMA;
+ }
+ else if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+ {
+ // Is the Force Unit Access bit set? If it is, then error. We
+ // aren't supporting this yet for normal DMA.
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_MOVE_FUA_BIT_ENABLE)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ status = sati_move_large_udma_translate_command(
+ sequence,
+ scsi_io,
+ ata_io,
+ sector_count,
+ ATA_WRITE_DMA_EXT,
+ ATA_READ_DMA_EXT
+ );
+ }
+ else if (sequence->device->capabilities & SATI_DEVICE_CAP_UDMA_ENABLE)
+ {
+ status = sati_move_large_udma_translate_command(
+ sequence,
+ scsi_io,
+ ata_io,
+ sector_count,
+ ATA_WRITE_DMA,
+ ATA_READ_DMA
+ );
+ }
+ else
+ {
+ /**
+ * Currently the translation does not support devices incapable of
+ * handling the 48-bit feature set (i.e. 16 bits of sector count).
+ */
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ return status;
+}
+
+/**
+ * @brief This method simply performs the functionality common to all
+ * payload data movement translations (i.e. READ/WRITE).
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] device_head This parameter specifies the current contents
+ * to be written to the ATA task file (register FIS) device
+ * head register.
+ *
+ * @return none
+ */
+void sati_move_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 device_head
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_device_head(
+ register_fis, device_head | ATA_DEV_HEAD_REG_LBA_MODE_ENABLE
+ );
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_move.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_move.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,121 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_MOVE_H_
+#define _SATI_MOVE_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ * common to translations that move data (i.e. read, write). It
+ * has code for the various different size CDBs (6, 10, 12, 16).
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_move_set_sector_count(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 is_fpdma_command
+);
+
+void sati_move_translate_32_bit_lba(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_move_translate_64_bit_lba(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_move_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_move_32_bit_lba_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 device_head
+);
+
+SATI_STATUS sati_move_small_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_move_large_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 * ata_device_head
+);
+
+void sati_move_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 device_head
+);
+
+#endif // _SATI_MOVE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_passthrough.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_passthrough.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,465 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI passthru command.
+ */
+
+#if !defined(DISABLE_SATI_PASSTHROUGH)
+
+#include <dev/isci/scil/sati.h>
+#include <dev/isci/scil/sati_passthrough.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+
+#define PASSTHROUGH_CDB_PROTOCOL_MASK 0x1E
+#define PASSTHROUGH_CDB_EXTEND_MASK 0x1
+#define PASSTHROUGH_CDB_CK_COND_MASK 0x20
+#define PASSTHROUGH_CDB_T_DIR_MASK 0x8
+
+#define PASSTHROUGH_ISOLATE_BITS(cdb, index, mask, shift) (((sati_get_cdb_byte(cdb, index) & mask) >> shift))
+
+#define PASSTHROUGH_CDB_PROTOCOL(cdb) PASSTHROUGH_ISOLATE_BITS(cdb, 1, PASSTHROUGH_CDB_PROTOCOL_MASK, 1)
+#define PASSTHROUGH_CDB_EXTEND(cdb) PASSTHROUGH_ISOLATE_BITS(cdb, 1, PASSTHROUGH_CDB_EXTEND_MASK, 0)
+#define PASSTHROUGH_CDB_CK_COND(cdb) PASSTHROUGH_ISOLATE_BITS(cdb, 2, PASSTHROUGH_CDB_CK_COND_MASK, 5)
+#define PASSTHROUGH_CDB_T_DIR(cdb) PASSTHROUGH_ISOLATE_BITS(cdb, 2, PASSTHROUGH_CDB_T_DIR_MASK, 3)
+
+#define PASSTHROUGH_CDB_MULTIPLE_COUNT(cdb) (sati_get_cdb_byte(cdb, 1) >> 5)
+#define PASSTHROUGH_CDB_COMMAND(cdb, index) sati_get_cdb_byte(cdb, index)
+
+// Protocols
+#define PASSTHROUGH_PIO_DATA_IN 0x4
+#define PASSTHROUGH_PIO_DATA_OUT 0x5
+#define PASSTHROUGH_UDMA_DATA_IN 0xA
+#define PASSTHROUGH_UDMA_DATA_OUT 0xB
+#define PASSTHROUGH_RETURN_RESPONSE 0xF
+
+/**
+* @brief This function will check the multiple_count field in the SCSI CDB
+* and if multiple_count is nonzero the function will check the
+* ATA command code. Only Read and Write Multiple commands are allowed
+* when multiple_count is a nonzero value.
+*
+* @param[in] cdb The SCSI cdb for the ATA pass-through command
+*
+* @return BOOL
+ @retval TRUE - multiple_count is nonzero with a unsupported command
+ @retval FALSE - multiple_count is zero or the command supports a nonzero value
+*/
+static
+BOOL sati_passthrough_multiple_count_error(
+ U8 * cdb
+)
+{
+ U8 ata_command_code;
+
+ if(PASSTHROUGH_CDB_MULTIPLE_COUNT(cdb) > 0)
+ {
+ if(sati_get_cdb_byte(cdb, 0 ) == SCSI_ATA_PASSTHRU_12)
+ {
+ ata_command_code = PASSTHROUGH_CDB_COMMAND(cdb, 9);
+ }
+ else
+ {
+ ata_command_code = PASSTHROUGH_CDB_COMMAND(cdb, 14);
+ }
+
+ switch(ata_command_code)
+ { //MULTICOUNT bit is supported
+ case ATA_READ_MULTIPLE:
+ case ATA_READ_MULTIPLE_EXT:
+ case ATA_WRITE_MULTIPLE:
+ case ATA_WRITE_MULTIPLE_EXT:
+ case ATA_WRITE_MULTIPLE_FUA_EXT:
+ return FALSE;
+ break;
+
+ default:
+ return TRUE;
+ }
+ }
+ //MULTICOUNT bit is not set
+ return FALSE;
+}
+
+/**
+ * @brief This method will construct the sense data buffer in the user's
+ * sense data buffer location. Additionally, it will set the user's
+ * SCSI status.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to construct the sense data.
+ * @param[in] register_fis This parameter specifies the fis from which
+ * to get the data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the sense data.
+ * @param[in] scsi_status This parameter specifies the SCSI status
+ * value for the user's IO request.
+ * @param[in] sense_key This parameter specifies the sense key to
+ * be set for the user's IO request.
+ * @param[in] additional_sense_code This parameter specifies the
+ * additional sense code (ASC) key to be set for the user's
+ * IO request.
+ * @param[in] additional_sense_code_qualifier This parameter specifies
+ * the additional sense code qualifier (ASCQ) key to be set
+ * for the user's IO request.
+ *
+ * @return none
+ */
+static
+void sati_passthrough_construct_sense(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 * register_fis,
+ void * scsi_io,
+ U8 scsi_status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 * sense_data;
+ U32 sense_len;
+ U8 * cdb;
+ unsigned char sector_count_upper;
+ unsigned char lba_upper;
+
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+ SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
+ sati_cb_get_response_iu_address(scsi_io);
+
+ sati_scsi_common_response_iu_construct(
+ rsp_iu,
+ scsi_status,
+ SCSI_FIXED_SENSE_DATA_BASE_LENGTH,
+ SCSI_RESPONSE_DATA_PRES_SENSE_DATA
+ );
+
+ sense_data = (U8*) rsp_iu->data;
+ sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes
+#else
+ sense_data = sati_cb_get_sense_data_address(scsi_io);
+ sense_len = sati_cb_get_sense_data_length(scsi_io);
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ scsi_status,
+ sense_key,
+ additional_sense_code,
+ additional_sense_code_qualifier
+ );
+
+ cdb = sati_cb_get_cdb_address(scsi_io);
+
+ if (sati_get_ata_sector_count_ext(register_fis) != 0) {
+ sector_count_upper = 1;
+ } else {
+ sector_count_upper = 0;
+ }
+
+ if (sati_get_ata_lba_high_ext(register_fis) != 0 ||
+ sati_get_ata_lba_mid_ext(register_fis) != 0 ||
+ sati_get_ata_lba_low_ext(register_fis) != 0) {
+ lba_upper = 1;
+ } else {
+ lba_upper = 0;
+ }
+
+ // Information section
+ sati_set_sense_data_byte(sense_data, sense_len, 3, (U8)sati_get_ata_error(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 4, (U8)sati_get_ata_status(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_device(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_sector_count(register_fis));
+
+ // Command specific section
+ sati_set_sense_data_byte(sense_data, sense_len, 8, (PASSTHROUGH_CDB_EXTEND(cdb) << 7) | (sector_count_upper << 6) | (lba_upper << 5));
+ sati_set_sense_data_byte(sense_data, sense_len, 9, sati_get_ata_lba_high(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 10, sati_get_ata_lba_mid(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 11, sati_get_ata_lba_low(register_fis));
+
+ sequence->is_sense_response_set = TRUE;
+}
+
+/**
+ * @brief This method will verify that the T_DIR bit matches the protocol bit.
+ * It will additionally set the direction on the sequence.
+ *
+ * @param[in,out] sequence This parameter specifies the translation sequence
+ * for which to construct the sense data.
+ * @param[in] cdb The CDB containing the passthrough command
+ *
+ * @return none
+ */
+static
+SATI_STATUS sati_passthrough_check_direction(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 * cdb
+)
+{
+ if ((PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_PIO_DATA_IN) ||
+ (PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_UDMA_DATA_IN))
+ {
+ if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x0)
+ {
+ return SATI_FAILURE;
+ }
+ else
+ {
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+ }
+ }
+ else if ((PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_PIO_DATA_OUT) ||
+ (PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_UDMA_DATA_OUT))
+ {
+ if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x1)
+ {
+ return SATI_FAILURE;
+ }
+ else
+ {
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+ }
+ }
+ else
+ {
+ sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+ }
+
+ return SATI_COMPLETE;
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI Passthrough command
+ * into the corresponding ATA command.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE This is returned if the command translation was
+ * unsuccessful
+ */
+
+SATI_STATUS sati_passthrough_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+ U8 * cdb;
+ U8 * register_fis;
+
+ status = SATI_FAILURE;
+
+ sequence->type = SATI_SEQUENCE_ATA_PASSTHROUGH_12;
+ sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
+
+ cdb = sati_cb_get_cdb_address(scsi_io);
+ sequence->protocol = PASSTHROUGH_CDB_PROTOCOL (cdb);
+ register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE
+ || sati_passthrough_multiple_count_error(cdb)
+ )
+ {
+ // Fail due to mismatch
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 3));
+ sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 4));
+ sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 5));
+ sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 6));
+ sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 7));
+ sati_set_ata_device_head(register_fis, sati_get_cdb_byte(cdb, 8));
+ sati_set_ata_command(register_fis, sati_get_cdb_byte(cdb, 9));
+
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the SCSI Passthrough command
+ * into the corresponding ATA command.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE This is returned if the command translation was
+ * unsuccessful
+ */
+SATI_STATUS sati_passthrough_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+ U8 * cdb;
+ U8 * register_fis;
+
+ status = SATI_FAILURE;
+
+ sequence->type = SATI_SEQUENCE_ATA_PASSTHROUGH_16;
+ sequence->state = SATI_SEQUENCE_STATE_TRANSLATE_DATA;
+
+ cdb = sati_cb_get_cdb_address(scsi_io);
+ sequence->protocol = PASSTHROUGH_CDB_PROTOCOL(cdb);
+ register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE
+ || sati_passthrough_multiple_count_error(cdb)
+ )
+ {
+ // Fail due to mismatch
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ if (PASSTHROUGH_CDB_EXTEND(cdb) == 1)
+ {
+ sati_set_ata_features_exp(register_fis, sati_get_cdb_byte(cdb, 3));
+ sati_set_ata_sector_count_exp(register_fis, sati_get_cdb_byte(cdb, 5));
+ sati_set_ata_lba_low_exp(register_fis, sati_get_cdb_byte(cdb, 7));
+ sati_set_ata_lba_mid_exp(register_fis, sati_get_cdb_byte(cdb, 9));
+ sati_set_ata_lba_high_exp(register_fis, sati_get_cdb_byte(cdb, 11));
+ }
+ sati_set_ata_features(register_fis, sati_get_cdb_byte(cdb, 4));
+ sati_set_ata_sector_count(register_fis, sati_get_cdb_byte(cdb, 6));
+ sati_set_ata_lba_low(register_fis, sati_get_cdb_byte(cdb, 8));
+ sati_set_ata_lba_mid(register_fis, sati_get_cdb_byte(cdb, 10));
+ sati_set_ata_lba_high(register_fis, sati_get_cdb_byte(cdb, 12));
+ sati_set_ata_device_head(register_fis, sati_get_cdb_byte(cdb, 13));
+ sati_set_ata_command(register_fis, sati_get_cdb_byte(cdb, 14));
+
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the ATA command
+ * response
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE This is returned if the command translation was
+ * unsuccessful
+ */
+SATI_STATUS sati_passthrough_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb;
+ U8 * register_fis;
+
+ cdb = sati_cb_get_cdb_address(scsi_io);
+ register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+ // Check for device errors
+ if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_translate_error(sequence, scsi_io, (U8)sati_get_ata_error(register_fis));
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // If the user set the check condition bit, fill out the sense data
+ if (PASSTHROUGH_CDB_CK_COND(cdb) ||
+ PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_RETURN_RESPONSE)
+ {
+ sati_passthrough_construct_sense(
+ sequence,
+ register_fis,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_RECOVERED_ERROR,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_ATA_PASS_THROUGH_INFORMATION_AVAILABLE
+ );
+ }
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+
+ return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_PASSTHROUGH)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_passthrough.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_passthrough.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,88 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_PASSTHROUGH_H_
+#define _SATI_PASSTHROUGH_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI passthrough command.
+ */
+
+#if !defined(DISABLE_SATI_PASSTHROUGH)
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_passthrough_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_passthrough_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_passthrough_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // !defined(DISABLE_SATI_PASSTHROUGH)
+
+#endif // _SATI_PASSTHROUGH_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,323 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI read (6, 10, 12, or 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_read.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the common translation functionality for
+ * all SCSI read operations that are 10 bytes in size or larger.
+ * Translated/Written items include:
+ * - Force Unit Access (FUA)
+ * - Sector Count/Transfer Length
+ * - Command register
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ * to be transferred by this request.
+ * @param[in] device_head This parameter points to device head register
+ * that is to be written into the ATA task file (register FIS).
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_set_sector_count() for additional return values.
+ */
+static
+SATI_STATUS sati_read_large_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 * device_head
+)
+{
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+
+ return sati_move_large_translate_command(
+ sequence,
+ scsi_io,
+ ata_io,
+ sector_count,
+ device_head
+ );
+}
+
+/**
+ * @brief This method performs the common translation functionality for
+ * all SCSI read operations containing a 32-bit logical block
+ * address.
+ * Translated/Written items include:
+ * - Logical Block Address (LBA)
+ * - Force Unit Access (FUA)
+ * - Sector Count/Transfer Length
+ * - Command register
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ * to be transferred by this request.
+ * @param[in] control_byte_offset This parameter specifies the byte offset
+ * into the command descriptor block at which the control byte
+ * is located.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_32_bit_lba_translate_command(), sati_move_set_sector_count()
+ * for additional return values.
+ */
+static
+SATI_STATUS sati_read_32_bit_lba_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 control_byte_offset
+)
+{
+ U8 device_head = 0;
+ SATI_STATUS status;
+
+ status = sati_read_large_translate_command(
+ sequence, scsi_io, ata_io, sector_count, &device_head
+ );
+
+ if (status == SATI_SUCCESS)
+ {
+ status = sati_move_32_bit_lba_translate_command(
+ sequence, scsi_io, ata_io, device_head
+ );
+ }
+
+ return status;
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI read command into a
+ * corresponding ATA read 6 command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the CDB.
+ */
+SATI_STATUS sati_read_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+ sequence->type = SATI_SEQUENCE_READ_6;
+
+ return sati_move_small_translate_command(sequence, scsi_io, ata_io);
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI read 10 command into a
+ * corresponding ATA read command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * It ensures that all translation required for this command is
+ * performed successfully.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_read_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_read_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ U32 sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_READ_10;
+
+ return sati_read_32_bit_lba_translate_command(
+ sequence, scsi_io, ata_io, sector_count, 9
+ );
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI read 12 command into a
+ * corresponding ATA read command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * It ensures that all translation required for this command is
+ * performed successfully.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_read_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_read_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
+ (sati_get_cdb_byte(cdb, 7) << 16) |
+ (sati_get_cdb_byte(cdb, 8) << 8) |
+ (sati_get_cdb_byte(cdb, 9));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_READ_12;
+
+ return sati_read_32_bit_lba_translate_command(
+ sequence, scsi_io, ata_io, sector_count, 11
+ );
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI read 16 command into a
+ * corresponding ATA read command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * It ensures that all translation required for this command is
+ * performed successfully.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_read_large_translate_command(), sati_move_translate_64_bit_lba()
+ * for additional return values.
+ */
+SATI_STATUS sati_read_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+ U8 device_head = 0;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
+ (sati_get_cdb_byte(cdb, 11) << 16) |
+ (sati_get_cdb_byte(cdb, 12) << 8) |
+ (sati_get_cdb_byte(cdb, 13));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_READ_16;
+
+ // Translate the sector count, write command register, and check various
+ // other parts of the CDB.
+ status = sati_read_large_translate_command(
+ sequence, scsi_io, ata_io, sector_count, &device_head
+ );
+
+ // Attempt to translate the 64-bit LBA field from the SCSI request
+ // into the 48-bits of LBA in the ATA register FIS.
+ if (status == SATI_SUCCESS)
+ {
+ sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+ status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+ }
+
+ return status;
+ }
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,91 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_READ_H_
+#define _SATI_READ_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ * required to translate the SCSI read (6, 10, 12, or 16-byte)
+ * commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_read_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_read_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_read_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_read_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_READ_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_buffer.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_buffer.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,235 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the implementation to translate
+* SCSI Read Buffer command based on the SAT spec.
+*/
+
+#if !defined(DISABLE_SATI_READ_BUFFER)
+
+#include <dev/isci/scil/sati_read_buffer.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+
+/**
+* @brief This method will translate the SCSI Read Buffer command
+* into a corresponding ATA Read Buffer command.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_command().
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_SUCCESS indicates that the translation was supported and occurred
+* without error.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+* there is a translation failure.
+* @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+* error, and no additional translation is necessary.
+*/
+SATI_STATUS sati_read_buffer_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ SATI_STATUS status = SATI_FAILURE;
+ U32 allocation_length;
+ U32 buffer_offset;
+
+ allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) |
+ (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8)));
+
+ buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) |
+ (sati_get_cdb_byte(cdb, 4) << 8) |
+ (sati_get_cdb_byte(cdb, 5)));
+
+ sequence->allocation_length = allocation_length;
+
+ switch(sati_get_cdb_byte(cdb, 1))
+ {
+ case SATI_READ_BUFFER_MODE_DATA:
+ if((allocation_length == 512) && (buffer_offset == 0) &&
+ (sati_get_cdb_byte(cdb, 2) == 0))
+ {
+ sati_ata_read_buffer_construct(ata_io, sequence);
+ sequence->type = SATI_SEQUENCE_READ_BUFFER;
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+ status = SATI_SUCCESS;
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ break;
+
+ case SATI_READ_BUFFER_MODE_DESCRIPTOR:
+
+ //allocation legnth must be at least four to return translated data
+ if(allocation_length < 4)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ //figure out if we support other buffer id's
+ sati_set_data_byte(sequence, scsi_io, 0, 0x09); //offset boundary
+ sati_set_data_byte(sequence, scsi_io, 1, 0x00);
+ sati_set_data_byte(sequence, scsi_io, 2, 0x02); //buffer capacity 0x200
+ sati_set_data_byte(sequence, scsi_io, 3, 0x00);
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_COMPLETE;
+ }
+ break;
+
+ default:
+ //Unspecified sat2v7, returning invalid cdb
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ return status;
+}
+
+/**
+* @brief This method will complete the Read Buffer Translation by copying the
+ ATA response data into the SCSI request DATA buffer.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_command().
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+* there is a translation failure.
+* @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+* error, and no additional translation is necessary.
+*/
+SATI_STATUS sati_read_buffer_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U8 ata_status = (U8) sati_get_ata_status(register_fis);
+ SATI_STATUS status = SATI_COMPLETE;
+
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ void * ata_data = sati_cb_get_ata_data_address(ata_io);
+
+ if(ata_data == NULL)
+ {
+ status = SATI_FAILURE;
+ }
+ else
+ {
+ //copy ATA data into SCSI data buffer
+ sati_copy_data(
+ sequence,
+ scsi_io,
+ 0,
+ ata_data,
+ 512
+ );
+ }
+ }
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ return status;
+}
+
+
+#endif //!defined(DISABLE_SATI_READ_BUFFER)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_buffer.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_buffer.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,82 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+* @file
+* @brief This file contains the method definitions to translate
+* SCSI Read Buffer command based of the SAT spec.
+*/
+
+#ifndef _SATI_READ_BUFFER_H_
+#define _SATI_READ_BUFFER_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_READ_BUFFER_MODE_DATA 0x02
+#define SATI_READ_BUFFER_MODE_DESCRIPTOR 0x03
+
+
+SATI_STATUS sati_read_buffer_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_read_buffer_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_READ_BUFFER_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_capacity.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_capacity.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,366 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI read capacity (10 byte) command.
+ */
+
+#if !defined(DISABLE_SATI_READ_CAPACITY)
+
+#include <dev/isci/scil/sati_read_capacity.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the read capacity 10 SCSI command into
+ * an ATA IDENTIFY DEVICE command.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ * LBA field is not 0, the PMI bit is not 0.
+ */
+SATI_STATUS sati_read_capacity_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ /**
+ * SAT dictates:
+ * - the LBA field must be 0
+ * - the PMI bit must be 0
+ */
+ if (
+ (
+ (sati_get_cdb_byte(cdb, 2) != 0)
+ || (sati_get_cdb_byte(cdb, 3) != 0)
+ || (sati_get_cdb_byte(cdb, 4) != 0)
+ || (sati_get_cdb_byte(cdb, 5) != 0)
+ )
+ || ((sati_get_cdb_byte(cdb, 8) & SCSI_READ_CAPACITY_PMI_BIT_ENABLE)
+ == 1)
+ )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // The CDB is properly formed.
+ sequence->allocation_length = SCSI_READ_CAPACITY_10_DATA_LENGTH;
+ sequence->type = SATI_SEQUENCE_READ_CAPACITY_10;
+
+ sati_ata_identify_device_construct(ata_io, sequence);
+ return SATI_SUCCESS;
+}
+
+
+
+/**
+ * @brief This method will translate the read capacity 16 SCSI command into
+ * an ATA IDENTIFY DEVICE command.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ * LBA field is not 0, the PMI bit is not 0.
+ */
+SATI_STATUS sati_read_capacity_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ /**
+ * SAT dictates:
+ * - the LBA field must be 0
+ * - the PMI bit must be 0
+ */
+ if (
+ (
+ (sati_get_cdb_byte(cdb, 2) != 0)
+ || (sati_get_cdb_byte(cdb, 3) != 0)
+ || (sati_get_cdb_byte(cdb, 4) != 0)
+ || (sati_get_cdb_byte(cdb, 5) != 0)
+ || (sati_get_cdb_byte(cdb, 6) != 0)
+ || (sati_get_cdb_byte(cdb, 7) != 0)
+ || (sati_get_cdb_byte(cdb, 8) != 0)
+ || (sati_get_cdb_byte(cdb, 9) != 0)
+ )
+ || ((sati_get_cdb_byte(cdb, 14) & SCSI_READ_CAPACITY_PMI_BIT_ENABLE)
+ == 1)
+ )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // The CDB is properly formed.
+ sequence->allocation_length = (sati_get_cdb_byte(cdb, 10) << 24) |
+ (sati_get_cdb_byte(cdb, 11) << 16) |
+ (sati_get_cdb_byte(cdb, 12) << 8) |
+ (sati_get_cdb_byte(cdb, 13));
+
+ sequence->type = SATI_SEQUENCE_READ_CAPACITY_16;
+
+ sati_ata_identify_device_construct(ata_io, sequence);
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the ATA Identify Device data into
+ * SCSI read capacity 10 data.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_data().
+ *
+ * @return none
+ */
+void sati_read_capacity_10_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+)
+{
+ U32 lba_low = 0;
+ U32 lba_high = 0;
+ U32 sector_size = 0;
+
+ // Extract the sector information (sector size, logical blocks) from
+ // the retrieved ATA identify device data.
+ sati_ata_identify_device_get_sector_info(
+ (ATA_IDENTIFY_DEVICE_DATA_T*)ata_input_data,
+ &lba_high,
+ &lba_low,
+ §or_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,
+ §or_size
+ );
+
+ // SATA drives report a value that is one LBA larger than the last LBA.
+ // SCSI wants the last LBA. Make the correction here. lba_low is
+ // always decremented since it is an unsigned long the value 0 will
+ // wrap to 0xFFFFFFFF.
+ if ((lba_low == 0) && (lba_high == 0))
+ lba_high -= 1;
+ lba_low -= 1;
+
+ // Build the CDB for Read Capacity 16
+ // Fill in the Logical Block Address bytes.
+ sati_set_data_byte(sequence, scsi_io, 0, (U8)((lba_high >> 24) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 1, (U8)((lba_high >> 16) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 2, (U8)((lba_high >> 8) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 3, (U8)(lba_high & 0xFF));
+
+ sati_set_data_byte(sequence, scsi_io, 4, (U8)((lba_low >> 24) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 5, (U8)((lba_low >> 16) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 6, (U8)((lba_low >> 8) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 7, (U8)(lba_low & 0xFF));
+
+ //Fill in the sector size field.
+ sati_set_data_byte(sequence, scsi_io, 8, (U8)((sector_size >> 24) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 9, (U8)((sector_size >> 16) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 10, (U8)((sector_size >> 8) & 0xFF));
+ sati_set_data_byte(sequence, scsi_io, 11, (U8)(sector_size & 0xFF));
+
+ //Check Bit 13 of ATA_IDENTIFY_DEVICE_DATA physical_logical_sector_info
+ //(Word 106) is enabled
+ physical_per_logical_enable_bit = (identify_device_data->physical_logical_sector_info
+ & ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_ENABLE);
+
+ //Extract the Physical per logical sector exponent field and calculate
+ //Physical per logical sector value
+ physical_per_logical_sector_exponent = (U8) (identify_device_data->physical_logical_sector_info
+ & ATA_IDENTIFY_LOGICAL_SECTOR_PER_PHYSICAL_SECTOR_MASK);
+ physical_per_logical_sector = 1 << (physical_per_logical_sector_exponent);
+
+ //If the data is valid, fill in the logical blocks per physical block exponent field.
+ //Else set logical blocks per physical block exponent to 1
+ if (physical_per_logical_enable_bit != 0)
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 13,
+ (U8)(physical_per_logical_sector_exponent & 0xFF)
+ );
+ else
+ sati_set_data_byte(sequence, scsi_io, 13, 0);
+
+ //Fill in the lowest aligned logical block address field.
+ logical_sector_alignment = identify_device_data->logical_sector_alignment;
+ if (logical_sector_alignment == 0)
+ scsi_logical_sector_alignment = 0;
+ else
+ scsi_logical_sector_alignment = (physical_per_logical_sector - logical_sector_alignment)
+ % physical_per_logical_sector;
+
+ //Follow SAT for reporting tprz and tpe
+ if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT) &&
+ (sequence->device->capabilities & SATI_DEVICE_CAP_DETERMINISTIC_READ_AFTER_TRIM))
+ {
+ // tpe
+ byte14 |= 0x80;
+ // tprz
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_READ_ZERO_AFTER_TRIM)
+ byte14 |= 0x40;
+ }
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 14,
+ (U8)(((scsi_logical_sector_alignment >>8) & 0x3F) | byte14));
+
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 15,
+ (U8)(scsi_logical_sector_alignment & 0xFF));
+}
+
+#endif // !defined(DISABLE_SATI_READ_CAPACITY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_read_capacity.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_read_capacity.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,91 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_READ_CAPACITY_H_
+#define _SATI_READ_CAPACITY_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to
+ * translate the SCSI read capacity (10 byte) command as well as
+ * translate data for both 10 byte and 16 byte read capacity flavors.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_read_capacity_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_read_capacity_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+void sati_read_capacity_10_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+void sati_read_capacity_16_translate_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * ata_input_data,
+ void * scsi_io
+);
+
+#endif // _SATI_READ_CAPACITY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_reassign_blocks.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_reassign_blocks.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,622 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI reassign blocks command.
+ */
+
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
+#include <dev/isci/scil/sati_reassign_blocks.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+// static SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T reassign_blocks_processing_state;
+
+/**
+ * @brief This method copies short 24bits LBA bytes to the command register
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+void set_current_lba(U8 * lba, void * ata_io)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_lba_low(register_fis, lba[0]);
+ sati_set_ata_lba_mid(register_fis, lba[1]);
+ sati_set_ata_lba_high(register_fis, lba[2]);
+ sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE | (lba[3] & 0x0F));
+
+
+}
+
+/**
+ * @brief This method copies short 48bits LBA bytes to the command register
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+void set_current_long_lba(U8 * lba, void * ata_io)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_lba_low(register_fis, lba[0]);
+ sati_set_ata_lba_mid(register_fis, lba[1]);
+ sati_set_ata_lba_high(register_fis, lba[2]);
+ sati_set_ata_lba_low_exp(register_fis, lba[3]);
+ sati_set_ata_lba_mid_exp(register_fis, lba[4]);
+ sati_set_ata_lba_high_exp(register_fis, lba[5]);
+}
+
+/**
+ * @brief This method performs the SCSI VERIFY command translation
+ * functionality.
+ * This includes:
+ * - setting the command register
+ * - setting the device head register
+ * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_reassign_blocks_verify_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_ata_non_data_command(ata_io, sequence);
+
+ // Ensure the device supports the 48 bit feature set.
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+ sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
+ else
+ sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method performs the SCSI Write sector command translation
+ * functionality.
+ * This includes:
+ * - setting the command register
+ * - setting the device head register
+ * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_reassign_blocks_write_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_ata_non_data_command(ata_io, sequence);
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+
+// sati_set_ata_sector_count(register_fis, 1);
+// status=sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
+
+ // Ensure the device supports the 48 bit feature set.
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+ sati_set_ata_command(register_fis, ATA_WRITE_DMA_EXT);
+ else
+ sati_set_ata_command(register_fis, ATA_WRITE_DMA);
+
+ return SATI_SUCCESS; //sati_move_set_sector_count(sequence,scsi_io,ata_io,1,0);
+}
+
+/**
+ * @brief This method performs the retrieving of parameter LBA praparation and setting
+ * processing flags before/after calling SCSI Verify sector command.
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_reassign_blocks_verify_condition(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 current_lba_bytes[8] = {0,0,0,0,0,0,0,0};
+ U32 lba_offset;
+ U8 page_size;
+ U32 index;
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+ lba_offset = sequence->command_specific_data.reassign_blocks_process_state.lba_offset;
+ page_size = sequence->command_specific_data.reassign_blocks_process_state.lba_size;
+
+ for(index = 0; index < page_size; index++)
+ {
+ sati_get_data_byte(sequence, scsi_io, lba_offset+index, ¤t_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, ¤t_lba_bytes[index]);
+ }
+
+ if (page_size == 4)
+ set_current_lba(current_lba_bytes, ata_io);
+ else
+ set_current_long_lba(current_lba_bytes, ata_io);
+
+ status = sati_reassign_blocks_write_command(sequence, scsi_io, ata_io);
+ sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba++;
+ sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_READY_TO_SEND;
+ return status ;
+}
+
+
+/**
+ * @brief This method will perform the pre-processing of Reassign Blocks command and parameter.
+ */
+static
+void sati_reassign_blocks_initial_processing(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U32 index;
+ U8 long_lba_bit;
+ U8 long_list_bit;
+ U8 lba_offset;
+ U8 page_size;
+ U32 data_transfer_length;
+ U8 header_bytes[4]={0,0,0,0};
+
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ //A long LBA (LONGLBA) bit set to zero specifies that the REASSIGN BLOCKS defective LBA list contains four-byte LBAs.
+ //A LONGLBA bit set to one specifies that the REASSIGN BLOCKS defective LBA list contains eight-byte LBAs.
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLBA_BIT) == 0)
+ {
+ long_lba_bit=0;
+ page_size = 4; //beginning of lba list
+ }
+ else
+ {
+ long_lba_bit=1;
+ page_size = 8;
+ }
+
+ //The long list (LONGLIST) bit specifies which parameter list header
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_REASSIGN_BLOCKS_LONGLIST_BIT) == 0)
+ {
+ long_list_bit=0;
+ }
+ else
+ {
+ long_list_bit=1;
+ }
+
+ sequence->allocation_length = 4; //Pre-set allocation_length so that the header can be retrieved
+
+ //Get 4 bytes for headers (byte 2 & byte 3 for short header; long header all 4 bytes)
+ for(index = 0; index < 4; index++)
+ {
+ sati_get_data_byte(sequence, scsi_io, index, &header_bytes[index]);
+ }
+
+ lba_offset = 4; //beginning of lba list
+
+ if (long_list_bit==0)
+ {
+ //Header byte 2 and 3 is the parameter list length
+ data_transfer_length = (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
+ }
+ else
+ {
+ //Header byte 0, 1, 2 and 3 contain the parameter list length
+ data_transfer_length = (header_bytes[0]<<24) + (header_bytes[1]<<16) +
+ (header_bytes[2]<<8) + header_bytes[3] + lba_offset;
+ }
+
+ sequence->allocation_length = data_transfer_length;
+
+ //Initialized the global processing state
+ sequence->command_specific_data.reassign_blocks_process_state.lba_size = page_size;
+ sequence->command_specific_data.reassign_blocks_process_state.lba_offset = lba_offset;
+ sequence->command_specific_data.reassign_blocks_process_state.ata_command_sent_for_current_lba = 0;
+ sequence->command_specific_data.reassign_blocks_process_state.block_lists_size = data_transfer_length - lba_offset;
+ sequence->command_specific_data.reassign_blocks_process_state.size_of_data_processed = 0;
+ sequence->command_specific_data.reassign_blocks_process_state.current_lba_processed = FALSE;
+ sequence->command_specific_data.reassign_blocks_process_state.ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
+}
+
+/**
+ * @brief This method will get the data size of not yet processed data.
+ *
+ * @param[in] lba_process_state This parameter points to the processing state fields
+ * of current block lba.
+ *
+ * @return This method returns the sizeof not yet processed data.
+ */
+static
+U32 sati_reassign_blocks_unprocessed_data_size(
+ SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * lba_process_state
+)
+{
+ U32 unprocessed_data_size;
+
+ if(lba_process_state->block_lists_size >= lba_process_state->size_of_data_processed)
+ {
+ unprocessed_data_size = lba_process_state->block_lists_size -
+ lba_process_state->size_of_data_processed;
+ }
+ else
+ {
+ unprocessed_data_size = 0;
+ }
+
+ return unprocessed_data_size;
+}
+
+
+/**
+ * @brief This method will check verify the sector and issue multiple ATA set feature commands to complete the translation.
+ *
+ * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
+ * of current lba block.
+ *
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_reassign_blocks_process_each_lba(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+ )
+{
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+ reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+ if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
+ (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
+ {
+ reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+ status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
+ }
+ else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 0)&&
+ (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
+ {
+ // point to next lba
+ reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+ reassign_blocks_process_state->lba_offset += reassign_blocks_process_state->lba_size;
+ status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
+ }
+ else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 1)&&
+ (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_FAIL))
+ {
+ reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+ status = sati_reassign_blocks_write_condition(sequence, scsi_io, ata_io);
+ }
+ else if((reassign_blocks_process_state->ata_command_sent_for_current_lba == 2) &&
+ (reassign_blocks_process_state->ata_command_status == SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS))
+ {
+ reassign_blocks_process_state->size_of_data_processed += reassign_blocks_process_state->lba_size;
+ status = sati_reassign_blocks_verify_condition(sequence, scsi_io, ata_io);
+ }
+ else //commands sent is 2; SATI_REASSIGN_BLOCKS_COMMAND_FAIL
+ {
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ return status;
+}
+
+/**
+ * @brief This method will process the each lba.
+ *
+ * @param[in] reassign_blocks_process_state This parameter points to the processing state fields
+ * of current lba.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ * @retval SATI_COMPLETE
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA
+ */
+static
+SATI_STATUS sati_reassign_blocks_process(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+
+ U32 page_size = 0; // in bytes
+ U32 size_of_data_to_be_processed;
+ U32 lba_offset;
+ SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+ reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+ lba_offset = reassign_blocks_process_state->lba_offset;
+ page_size = reassign_blocks_process_state->lba_size;
+
+
+ if(sati_reassign_blocks_unprocessed_data_size(reassign_blocks_process_state) < page_size)
+ {
+ return status;
+ }
+
+ // Any more lba blocks? If not, done.
+ if(reassign_blocks_process_state->block_lists_size ==
+ reassign_blocks_process_state->size_of_data_processed)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_COMPLETE;
+ }
+ //start processing next lba
+ else
+ {
+ size_of_data_to_be_processed = reassign_blocks_process_state->block_lists_size
+ - reassign_blocks_process_state->size_of_data_processed;
+
+ status = sati_reassign_blocks_process_each_lba(sequence, scsi_io, ata_io);
+
+ }
+
+ return status;
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI Reassign Blocks command
+ * into corresponding ATA commands. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * Additionally, in some cases more than a single ATA command may
+ * be required.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ * successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the parameter data fields.
+ */
+SATI_STATUS sati_reassign_blocks_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+ reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+ sequence->type = SATI_SEQUENCE_REASSIGN_BLOCKS;
+
+ //Initial processing if
+ if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+ {
+ sati_reassign_blocks_initial_processing(
+ sequence,
+ scsi_io,
+ ata_io
+ );
+ }
+
+ // start processing current lba
+ if(reassign_blocks_process_state->current_lba_processed)
+ {
+ reassign_blocks_process_state->ata_command_sent_for_current_lba = 0;
+ reassign_blocks_process_state->current_lba_processed = FALSE;
+ }
+
+ status = sati_reassign_blocks_process(sequence, scsi_io, ata_io);
+
+ if(reassign_blocks_process_state->block_lists_size ==
+ reassign_blocks_process_state->size_of_data_processed)
+ {
+ // Done this lba
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ }
+ else
+ {
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+
+ if(status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_MEDIUM_ERROR,
+ SCSI_ASC_UNRECOVERED_READ_ERROR,
+ SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
+ );
+ }
+
+ return status;
+}
+
+/**
+ * @brief This method will translate the ATA command register FIS
+ * response into an appropriate SCSI response for Reassign Blocks
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the data translation was
+ * successful.
+ */
+SATI_STATUS sati_reassign_blocks_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T * reassign_blocks_process_state;
+
+ reassign_blocks_process_state = &sequence->command_specific_data.reassign_blocks_process_state;
+
+ if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_FAIL;
+
+ //Checking for the number of ATA commands attempted on current LBA, stop
+ //the seaquence after 2 commands have returned errors.
+ if(reassign_blocks_process_state->ata_command_sent_for_current_lba < 2)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ reassign_blocks_process_state->size_of_data_processed -= reassign_blocks_process_state->lba_size;
+ return SATI_SEQUENCE_INCOMPLETE;
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_MEDIUM_ERROR,
+ SCSI_ASC_UNRECOVERED_READ_ERROR,
+ SCSI_ASCQ_UNRECOVERED_READ_ERROR_AUTO_REALLOCATE_FAIL
+ );
+ }
+
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ reassign_blocks_process_state->ata_command_status = SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS;
+ if (reassign_blocks_process_state->ata_command_sent_for_current_lba != 2)
+ reassign_blocks_process_state->current_lba_processed = TRUE;
+
+ if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ return SATI_SEQUENCE_INCOMPLETE;
+ }
+ }
+ return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_reassign_blocks.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_reassign_blocks.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,80 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_REASSIGN_BLOCKS_H_
+#define _SATI_REASSIGN_BLOCKS_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI reassign blocks command.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+
+
+SATI_STATUS sati_reassign_blocks_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_reassign_blocks_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_REASSIGN_BLOCKS_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_report_luns.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_report_luns.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,124 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI REPORT LUNS command.
+ */
+
+#if !defined(DISABLE_SATI_REPORT_LUNS)
+
+#include <dev/isci/scil/sati_report_luns.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the REPORT LUN SCSI command. This
+ * command is immediately completed, since there is no applicable
+ * ATA/ATAPI command. The data payload is written and SATI_COMPLETE
+ * is always returned.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return This method always indicates the translation is complete.
+ * @retval SATI_COMPLETE This value is always returned.
+ */
+SATI_STATUS sati_report_luns_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ // Set the data length based on the allocation length field in the CDB.
+ sequence->allocation_length = (sati_get_cdb_byte(cdb, 6) << 24) |
+ (sati_get_cdb_byte(cdb, 7) << 16) |
+ (sati_get_cdb_byte(cdb, 8) << 8) |
+ (sati_get_cdb_byte(cdb, 9));
+
+ // The first 4 bytes indicate the length of the LUN list. Each
+ // LUN entry is 8 bytes. There is only ever LUN 0 for ATA/ATAPI
+ // devices. The value reported is: n-7, where n is the last byte
+ // offset (i.e. 15) in the REPORT LUN data.
+ sati_set_data_byte(sequence, scsi_io, 0, 0);
+ sati_set_data_byte(sequence, scsi_io, 1, 0);
+ sati_set_data_byte(sequence, scsi_io, 2, 0);
+ sati_set_data_byte(sequence, scsi_io, 3, 8);
+
+ // Bytes 4-7 are reserved.
+ sati_set_data_byte(sequence, scsi_io, 4, 0);
+ sati_set_data_byte(sequence, scsi_io, 5, 0);
+ sati_set_data_byte(sequence, scsi_io, 6, 0);
+ sati_set_data_byte(sequence, scsi_io, 7, 0);
+
+ // Add in our single LUN of zero.
+ sati_set_data_byte(sequence, scsi_io, 8, 0);
+ sati_set_data_byte(sequence, scsi_io, 9, 0);
+ sati_set_data_byte(sequence, scsi_io, 10, 0);
+ sati_set_data_byte(sequence, scsi_io, 11, 0);
+ sati_set_data_byte(sequence, scsi_io, 12, 0);
+ sati_set_data_byte(sequence, scsi_io, 13, 0);
+ sati_set_data_byte(sequence, scsi_io, 14, 0);
+ sati_set_data_byte(sequence, scsi_io, 15, 0);
+
+ return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_REPORT_LUNS)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_report_luns.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_report_luns.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,75 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_REPORT_LUNS_H_
+#define _SATI_REPORT_LUNS_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type defintions
+ * required to translate the SCSI REPORT LUNS command.
+ */
+
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#if !defined(DISABLE_SATI_REPORT_LUNS)
+SATI_STATUS sati_report_luns_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+#else // !(defined)DISABLE_SATI_REPORT_LUNS
+#define sati_report_luns_translate_command(sequence, scsi_io, ata_io) SATI_FAILURE
+#endif // !(defined)DISABLE_SATI_REPORT_LUNS
+
+#endif // _SATI_REPORT_LUNS_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_request_sense.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_request_sense.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,353 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the implementation to translate
+ * SCSI Request Sense command based of the SAT spec.
+ */
+
+#if !defined(DISABLE_SATI_REQUEST_SENSE)
+
+#include <dev/isci/scil/sati_request_sense.h>
+#include <dev/isci/scil/sati_device.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_mode_pages.h>
+
+#define MRIE_BYTE 3
+#define DEXCPT_BYTE 2
+
+/**
+ * @brief This method will translate the SCSI request sense command
+ * into corresponding ATA commands. Depending on supported and enabled
+ * capabilities like SMART, different ATA commands can be selected.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicates if the command translation succeeded.
+ * @retval SATI_SUCCESS indicates that the translation was supported and occurred
+ * without error.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * the SATII is processing a format unit commmand.
+ * @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+ * error, and no additional translation is necessary.
+ */
+SATI_STATUS sati_request_sense_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ //check if SATI is processing format unit command
+ switch(sequence->device->state)
+ {
+ case SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_NOT_READY,
+ SCSI_ASC_LUN_FORMAT_IN_PROGRESS,
+ SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS
+ );
+ return SATI_COMPLETE;
+ break;
+
+ case SATI_DEVICE_STATE_UNIT_ATTENTION_CONDITION:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_UNIT_ATTENTION,
+ sequence->device->unit_attention_asc,
+ sequence->device->unit_attention_ascq
+ );
+ return SATI_COMPLETE;
+ break;
+ //sending sense data status Idle, this is set by start_stop_unit
+ case SATI_DEVICE_STATE_IDLE:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_POWER_STATE_CHANGE,
+ SCSI_ASCQ_IDLE_CONDITION_ACTIVATE_BY_COMMAND
+ );
+ return SATI_COMPLETE;
+ break;
+ //sending sense data status Standby, this is set by start_stop_unit
+ case SATI_DEVICE_STATE_STANDBY:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_POWER_STATE_CHANGE,
+ SCSI_ASCQ_STANDBY_CONDITION_ACTIVATE_BY_COMMAND
+ );
+ return SATI_COMPLETE;
+ break;
+
+ case SATI_DEVICE_STATE_STOPPED:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ return SATI_COMPLETE;
+ break;
+
+ default:
+ break;
+ }
+
+ sequence->allocation_length = sati_get_cdb_byte(cdb, 4);
+
+ //Check if the device has SMART support & SMART enabled
+ if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_SUPPORT)
+ {
+ if(sequence->device->capabilities & SATI_DEVICE_CAP_SMART_ENABLE)
+ {
+ sati_ata_smart_return_status_construct(
+ ata_io,
+ sequence,
+ ATA_SMART_SUB_CMD_RETURN_STATUS
+ );
+
+ sequence->type = SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS;
+ return SATI_SUCCESS;
+ }
+ }
+ sati_ata_check_power_mode_construct(ata_io, sequence);
+ sequence->type = SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE;
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the response to the SATI Request Sense
+ * translation. ATA_Check_Power_Mode and ATA_SMART_Return_Status will
+ * be translated into a SCSI sense data response.
+ *
+ * @return SATI_STATUS Indicates if the response translation succeeded.
+ *
+ */
+SATI_STATUS sati_request_sense_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U32 mid_register;
+ U32 high_register;
+ U32 sector_count;
+ SATI_STATUS status = SATI_FAILURE;
+
+ if(sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE ,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ switch(sequence->type)
+ {
+ case SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS:
+
+ mid_register = sati_get_ata_lba_mid(register_fis);
+ high_register = sati_get_ata_lba_high(register_fis);
+ if(mid_register == ATA_MID_REGISTER_THRESHOLD_EXCEEDED
+ && high_register == ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED)
+ {
+ sati_request_sense_data_response_construct(
+ sequence,
+ scsi_io,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_HARDWARE_IMPENDING_FAILURE,
+ SCSI_ASCQ_GENERAL_HARD_DRIVE_FAILURE
+ );
+ status = SATI_COMPLETE;
+ }
+ else
+ {
+ sati_request_sense_data_response_construct(
+ sequence,
+ scsi_io,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_COMPLETE;
+ }
+ break;
+
+ case SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE:
+
+ sector_count = sati_get_ata_sector_count(register_fis);
+
+ switch(sector_count)
+ {
+ case ATA_STANDBY_POWER_MODE:
+ sati_request_sense_data_response_construct(
+ sequence,
+ scsi_io,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_POWER_STATE_CHANGE,
+ SCSI_ASCQ_POWER_STATE_CHANGE_TO_STANDBY
+ );
+ status = SATI_COMPLETE;
+ break;
+
+ case ATA_IDLE_POWER_MODE:
+ sati_request_sense_data_response_construct(
+ sequence,
+ scsi_io,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_POWER_STATE_CHANGE,
+ SCSI_ASCQ_POWER_STATE_CHANGE_TO_IDLE
+ );
+ status = SATI_COMPLETE;
+ break;
+
+ case ATA_ACTIVE_POWER_MODE:
+ sati_request_sense_data_response_construct(
+ sequence,
+ scsi_io,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_COMPLETE;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ sati_request_sense_data_response_construct(
+ sequence,
+ scsi_io,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_COMPLETE;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * @brief This method will construct a response for the sati_request_sense
+ * translation. The response will be returned in the data buffer instead
+ * of the response buffer, using sense data format described in SPC-4.
+ *
+ */
+void sati_request_sense_data_response_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ sati_set_data_byte(
+ sequence,
+ scsi_io,
+ 0,
+ SCSI_FIXED_CURRENT_RESPONSE_CODE | SCSI_FIXED_SENSE_DATA_VALID_BIT
+ );
+
+ sati_set_data_byte(sequence, scsi_io, 1, 0);
+ sati_set_data_byte(sequence, scsi_io, 2, sense_key);
+ sati_set_data_byte(sequence, scsi_io, 3, 0);
+ sati_set_data_byte(sequence, scsi_io, 4, 0);
+ sati_set_data_byte(sequence, scsi_io, 5, 0);
+ sati_set_data_byte(sequence, scsi_io, 6, 0);
+ sati_set_data_byte(sequence, scsi_io, 7, 0);
+ sati_set_data_byte(sequence, scsi_io, 8, 0);
+ sati_set_data_byte(sequence, scsi_io, 9, 0);
+ sati_set_data_byte(sequence, scsi_io, 10, 0);
+ sati_set_data_byte(sequence, scsi_io, 11, 0);
+ sati_set_data_byte(sequence, scsi_io, 12, additional_sense_code);
+ sati_set_data_byte(sequence, scsi_io, 13, additional_sense_code_qualifier);
+ sati_set_data_byte(sequence, scsi_io, 14, 0);
+ sati_set_data_byte(sequence, scsi_io, 15, 0);
+ sati_set_data_byte(sequence, scsi_io, 16, 0);
+ sati_set_data_byte(sequence, scsi_io, 17, 0);
+}
+
+#endif // !defined(DISABLE_SATI_REQUEST_SENSE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_request_sense.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_request_sense.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,86 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the method definitions to translate
+ * SCSI Request Sense command based of the SAT spec.
+ */
+
+#ifndef _SATI_REQUEST_SENSE_H_
+#define _SATI_REQUEST_SENSE_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_request_sense_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_request_sense_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+void sati_request_sense_data_response_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+);
+
+#endif // _SATI_REQUEST_SENSE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_start_stop_unit.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_start_stop_unit.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,404 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI start stop unit command.
+ */
+
+#if !defined(DISABLE_SATI_START_STOP_UNIT)
+
+#include <dev/isci/scil/sati_start_stop_unit.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the start stop unit SCSI command into
+ * various ATA commands depends on the value in POWER CONTIDTION, LOEJ
+ * and START fields.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA Please refer to spec.
+ *
+ */
+SATI_STATUS sati_start_stop_unit_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ switch ( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) )
+ {
+ case SCSI_START_STOP_UNIT_POWER_CONDITION_START_VALID:
+ if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0
+ && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 )
+ {
+ if ( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 1 )
+ {
+ //directly send ATA STANDBY_IMMEDIATE
+ sati_ata_standby_immediate_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
+ }
+ else
+ {
+ if ( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+ {
+ //First, send ATA flush command.
+ sati_ata_flush_cache_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+
+ //remember there is next step.
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+ else
+ {
+ //the first step, flush cache command, has completed.
+ //Send standby immediate now.
+ sati_ata_standby_immediate_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
+
+ }
+ }
+ }
+ else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 0
+ && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 )
+ {
+ //need to know whether the device supports removable medial feature set.
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_REMOVABLE_MEDIA)
+ {
+ //send ATA MEDIA EJECT command.
+ sati_ata_media_eject_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_MEDIA_EJECT;
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ }
+ else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1
+ && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 0 )
+ {
+ //send an ATA verify command
+ sati_ata_read_verify_sectors_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS;
+ }
+ else if ( SATI_START_STOP_UNIT_START_BIT(cdb) == 1
+ && SATI_START_STOP_UNIT_LOEJ_BIT(cdb) == 1 )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ break;
+ //Power Condition Field is set to 0x01(Device to transition to Active state)
+ case SCSI_START_STOP_UNIT_POWER_CONDITION_ACTIVE:
+
+ if( sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+ {
+ sati_ata_idle_construct(ata_io, sequence);
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ sequence->command_specific_data.translated_command = ATA_IDLE;
+ }
+ else
+ {
+ sati_ata_read_verify_sectors_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_READ_VERIFY_SECTORS;
+ }
+ break;
+
+ //Power Condition Field is set to 0x02(Device to transition to Idle state)
+ case SCSI_START_STOP_UNIT_POWER_CONDITION_IDLE:
+
+ if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
+ sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+ {
+ sati_ata_flush_cache_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+ else
+ {
+ if( SATI_START_STOP_UNIT_POWER_CONDITION_MODIFIER(cdb) == 0 )
+ {
+ sati_ata_idle_immediate_construct(ata_io, sequence);
+ }
+ else
+ {
+ sati_ata_idle_immediate_unload_construct(ata_io, sequence);
+ }
+ sequence->command_specific_data.translated_command = ATA_IDLE_IMMED;
+ }
+ break;
+
+ //Power Condition Field is set to 0x03(Device to transition to Standby state)
+ case SCSI_START_STOP_UNIT_POWER_CONDITION_STANDBY:
+ if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
+ sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+ {
+ sati_ata_flush_cache_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+ else
+ {
+ sati_ata_standby_immediate_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_STANDBY_IMMED;
+ }
+ break;
+
+ //Power Condition Field is set to 0xB(force Standby state)
+ case SCSI_START_STOP_UNIT_POWER_CONDITION_FORCE_S_CONTROL:
+
+ if( SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) == 0 &&
+ sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE )
+ {
+ sati_ata_flush_cache_construct(ata_io, sequence);
+ sequence->command_specific_data.translated_command = ATA_FLUSH_CACHE;
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+ else
+ {
+ sati_ata_standby_construct(ata_io, sequence, 0);
+ sequence->command_specific_data.translated_command = ATA_STANDBY;
+ }
+ break;
+
+ case SCSI_START_STOP_UNIT_POWER_CONDITION_LU_CONTROL:
+ default: //TBD.
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+
+ if ( SATI_START_STOP_UNIT_IMMED_BIT(cdb) == 1 )
+ {
+ //@todo: return good status now.
+ ;
+ }
+ sequence->type = SATI_SEQUENCE_START_STOP_UNIT;
+ return SATI_SUCCESS;
+}
+
+
+/**
+ * @brief This method will translate the ATA command register FIS
+ * response into an appropriate SCSI response for START STOP UNIT.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the data translation was
+ * successful.
+ */
+SATI_STATUS sati_start_stop_unit_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+
+ if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ switch ( sequence->command_specific_data.translated_command )
+ {
+ case ATA_FLUSH_CACHE:
+ case ATA_STANDBY_IMMED:
+ case ATA_IDLE_IMMED:
+ case ATA_IDLE:
+ case ATA_STANDBY:
+ //Note: There is lack of reference in spec of the error handling for
+ //READ_VERIFY command.
+ case ATA_READ_VERIFY_SECTORS:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_COMMAND_SEQUENCE_ERROR,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ break;
+
+ case ATA_MEDIA_EJECT:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ break;
+
+ default:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ break;
+ }
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ switch ( sequence->command_specific_data.translated_command )
+ {
+ case ATA_READ_VERIFY_SECTORS:
+
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ //device state is now operational(active)
+ sequence->device->state = SATI_DEVICE_STATE_OPERATIONAL;
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ break;
+
+ case ATA_IDLE_IMMED:
+
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ sequence->device->state = SATI_DEVICE_STATE_IDLE;
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ break;
+
+ //These three commands will be issued when the power condition is 0x00 or 0x03
+ case ATA_MEDIA_EJECT:
+ case ATA_STANDBY:
+ case ATA_STANDBY_IMMED:
+
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_NO_SENSE,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+
+ if( SATI_START_STOP_UNIT_POWER_CONDITION(cdb) == 0 )
+ {
+ sequence->device->state = SATI_DEVICE_STATE_STOPPED;
+ }
+ else
+ {
+ sequence->device->state = SATI_DEVICE_STATE_STANDBY;
+ }
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ break;
+
+ default:
+ //FLUSH Cache command does not require any success handling
+ break;
+ }
+
+ if (sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ return SATI_SEQUENCE_INCOMPLETE;
+ }
+ }
+ return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_START_STOP_UNIT)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_start_stop_unit.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_start_stop_unit.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,102 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_START_STOP_UNIT_H_
+#define _SATI_START_STOP_UNIT_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ * required to translate the SCSI start_stop_unit commands.
+ */
+
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_START_STOP_UNIT_POWER_CONDITION(cdb) \
+ (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_POWER_CONDITION_MASK ) \
+ >> SCSI_START_STOP_UNIT_POWER_CONDITION_SHIFT)
+
+#define SATI_START_STOP_UNIT_START_BIT(cdb) \
+ (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_START_BIT_MASK ) \
+ >> SCSI_START_STOP_UNIT_START_BIT_SHIFT)
+
+#define SATI_START_STOP_UNIT_LOEJ_BIT(cdb) \
+ (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_LOEJ_BIT_MASK ) \
+ >> SCSI_START_STOP_UNIT_LOEJ_BIT_SHIFT)
+
+#define SATI_START_STOP_UNIT_NO_FLUSH_BIT(cdb) \
+ (( sati_get_cdb_byte(cdb, 4) & SCSI_START_STOP_UNIT_NO_FLUSH_MASK ) \
+ >> SCSI_START_STOP_UNIT_NO_FLUSH_SHIFT)
+
+#define SATI_START_STOP_UNIT_IMMED_BIT(cdb) \
+ (( sati_get_cdb_byte(cdb, 1) & SCSI_START_STOP_UNIT_IMMED_MASK ) \
+ >> SCSI_START_STOP_UNIT_IMMED_SHIFT)
+
+#define SATI_START_STOP_UNIT_POWER_CONDITION_MODIFIER(cdb) \
+ (( sati_get_cdb_byte(cdb, 3) & SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_MASK) \
+ >> SCSI_START_STOP_UNIT_POWER_CONDITION_MODIFIER_SHIFT)
+
+SATI_STATUS sati_start_stop_unit_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_start_stop_unit_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+#endif // _SATI_START_STOP_UNIT_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_synchronize_cache.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_synchronize_cache.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,119 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations for translating
+ * the SCSI SYNCHRONIZE_CACHE (10, 16-byte) commands.
+ */
+
+#if !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+
+#include <dev/isci/scil/sati_synchronize_cache.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the SCSI SYNCHRONIZE_CACHE 10 and 16 command translation
+ * functionality common to all SYNCHRONIZE_CACHE command sizes.
+ * This includes:
+ * - setting the command register
+ * - setting the device head register
+ * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_synchronize_cache_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sequence->type = SATI_SEQUENCE_SYNCHRONIZE_CACHE;
+ sequence->protocol = SAT_PROTOCOL_NON_DATA;
+ sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+
+ if (sati_get_cdb_byte(cdb, 1) & SCSI_SYNCHRONIZE_CACHE_IMMED_ENABLED)
+ {
+ //currently we ignore immed bit.
+ ;
+ }
+
+ // Ensure the device supports the 48 bit feature set.
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+ sati_set_ata_command(register_fis, ATA_FLUSH_CACHE_EXT);
+ else
+ sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
+
+ return SATI_SUCCESS;
+}
+
+#endif // !defined(DISABLE_SATI_SYNCHRONIZE_CACHE)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_synchronize_cache.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_synchronize_cache.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,71 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_SYNCHRONIZE_CACHE_H_
+#define _SATI_SYNCHRONIZE_CACHE_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes and constructs
+ * for translating the SCSI SYNCHRONIZE CACHE (10, 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_synchronize_cache_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_SYNCHRONIZE_CACHE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_test_unit_ready.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_test_unit_ready.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,186 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI test unit ready command.
+ */
+
+#if !defined(DISABLE_SATI_TEST_UNIT_READY)
+
+#include <dev/isci/scil/sati_test_unit_ready.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+ * @brief This method will translate the test unit ready SCSI command into
+ * an ATA CHECK POWER MODE command.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if the
+ * LBA field is not 0, the PMI bit is not 0.
+ */
+SATI_STATUS sati_test_unit_ready_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ /**
+ * SAT dictates:
+ * - the device should be in a state to receive commands
+ * - a stopped device should cause sense data.
+ * - a format unit in progresss should cause sense data.
+ * - a self-test in progress should cause sense data.
+ * - a device fault occurred on previous request should cause sense data.
+ * - handling the removable media feature set isn't supported according to
+ * SAT specifications.
+ */
+ if (sequence->device->state == SATI_DEVICE_STATE_STOPPED)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_NOT_READY,
+ SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
+ SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else if (sequence->device->state
+ == SATI_DEVICE_STATE_SELF_TEST_IN_PROGRESS)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_NOT_READY,
+ SCSI_ASC_LUN_SELF_TEST_IN_PROGRESS,
+ SCSI_ASCQ_LUN_SELF_TEST_IN_PROGRESS
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else if (sequence->device->state
+ == SATI_DEVICE_STATE_FORMAT_UNIT_IN_PROGRESS)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_NOT_READY,
+ SCSI_ASC_LUN_FORMAT_IN_PROGRESS,
+ SCSI_ASCQ_LUN_FORMAT_IN_PROGRESS
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // The CDB is properly formed and the device is ready.
+ sequence->type = SATI_SEQUENCE_TEST_UNIT_READY;
+
+ sati_ata_check_power_mode_construct(ata_io, sequence);
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method will translate the ATA CHECK POWER MODE register FIS
+ * response into an appropriate SCSI response.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the data translation was
+ * successful.
+ */
+SATI_STATUS sati_test_unit_ready_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+ /**
+ * SAT dictates:
+ * - If the ATA CHECK POWER MODE command returns an error, then
+ * return sense data indicating the LOGICAL UNIT DOES NOT RESPONSE
+ * TO SELECTION.
+ * - All other cases are considered successful.
+ */
+ if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_NOT_READY,
+ SCSI_ASC_LUN_NOT_RESPOND_TO_SELECTION,
+ SCSI_ASCQ_LUN_NOT_RESPOND_TO_SELECTION
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ return SATI_COMPLETE;
+}
+
+#endif // !defined(DISABLE_SATI_TEST_UNIT_READY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_test_unit_ready.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_test_unit_ready.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,79 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_TEST_UNIT_READY_H_
+#define _SATI_TEST_UNIT_READY_H_
+
+/**
+ * @file
+ * @brief This file contains the method interfaces required to
+ * translate the SCSI test unit ready command and corresponding
+ * ATA responses.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_test_unit_ready_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * translator_sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_test_unit_ready_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * translator_sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_TEST_UNIT_READY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_translator_sequence.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_translator_sequence.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,361 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_TRANSLATOR_SEQUENCE_H_
+#define _SATI_TRANSLATOR_SEQUENCE_H_
+
+/**
+ * @file
+ * @brief This file contains all of the defintions for the SATI translator
+ * sequence. A translator sequence is simply a defintion for the
+ * various sequences of commands that occur in this translator.
+ */
+
+#include <dev/isci/scil/sati_device.h>
+
+/**
+ * @enum _SATI_TRANSLATOR_SEQUENCE_TYPE
+ *
+ * @brief This enumeration defines the possible sequence types for the
+ * translator.
+ */
+typedef enum _SATI_TRANSLATOR_SEQUENCE_TYPE
+{
+ // SCSI Primary Command (SPC) sequences.
+ SATI_SEQUENCE_REPORT_LUNS,
+ SATI_SEQUENCE_TEST_UNIT_READY,
+ SATI_SEQUENCE_INQUIRY_STANDARD,
+ SATI_SEQUENCE_INQUIRY_SUPPORTED_PAGES,
+ SATI_SEQUENCE_INQUIRY_SERIAL_NUMBER,
+ SATI_SEQUENCE_INQUIRY_DEVICE_ID,
+ SATI_SEQUENCE_INQUIRY_ATA_INFORMATION,
+ SATI_SEQUENCE_INQUIRY_BLOCK_DEVICE,
+ SATI_SEQUENCE_INQUIRY_EXECUTE_DEVICE_DIAG,
+ SATI_SEQUENCE_MODE_SENSE_6_CACHING,
+ SATI_SEQUENCE_MODE_SENSE_6_INFORMATIONAL_EXCP_CONTROL,
+ SATI_SEQUENCE_MODE_SENSE_6_READ_WRITE_ERROR,
+ SATI_SEQUENCE_MODE_SENSE_6_DISCONNECT_RECONNECT,
+ SATI_SEQUENCE_MODE_SENSE_6_CONTROL,
+ SATI_SEQUENCE_MODE_SENSE_6_POWER_CONDITION,
+ SATI_SEQUENCE_MODE_SENSE_6_ALL_PAGES,
+ SATI_SEQUENCE_MODE_SENSE_10_CACHING,
+ SATI_SEQUENCE_MODE_SENSE_10_INFORMATIONAL_EXCP_CONTROL,
+ SATI_SEQUENCE_MODE_SENSE_10_READ_WRITE_ERROR,
+ SATI_SEQUENCE_MODE_SENSE_10_DISCONNECT_RECONNECT,
+ SATI_SEQUENCE_MODE_SENSE_10_CONTROL,
+ SATI_SEQUENCE_MODE_SENSE_10_POWER_CONDITION,
+ SATI_SEQUENCE_MODE_SENSE_10_ALL_PAGES,
+ SATI_SEQUENCE_MODE_SELECT_MODE_PAGE_CACHING,
+ SATI_SEQUENCE_MODE_SELECT_MODE_POWER_CONDITION,
+ SATI_SEQUENCE_MODE_SELECT_MODE_INFORMATION_EXCEPT_CONTROL,
+
+ //Log Sense Sequences
+ SATI_SEQUENCE_LOG_SENSE_SELF_TEST_LOG_PAGE,
+ SATI_SEQUENCE_LOG_SENSE_EXTENDED_SELF_TEST_LOG_PAGE,
+ SATI_SEQUENCE_LOG_SENSE_SUPPORTED_LOG_PAGE,
+ SATI_SEQUENCE_LOG_SENSE_INFO_EXCEPTION_LOG_PAGE,
+
+ // SCSI Block Command (SBC) sequences.
+
+ SATI_SEQUENCE_READ_6,
+ SATI_SEQUENCE_READ_10,
+ SATI_SEQUENCE_READ_12,
+ SATI_SEQUENCE_READ_16,
+
+ SATI_SEQUENCE_READ_CAPACITY_10,
+ SATI_SEQUENCE_READ_CAPACITY_16,
+
+ SATI_SEQUENCE_SYNCHRONIZE_CACHE,
+
+ SATI_SEQUENCE_VERIFY_10,
+ SATI_SEQUENCE_VERIFY_12,
+ SATI_SEQUENCE_VERIFY_16,
+
+ SATI_SEQUENCE_WRITE_6,
+ SATI_SEQUENCE_WRITE_10,
+ SATI_SEQUENCE_WRITE_12,
+ SATI_SEQUENCE_WRITE_16,
+
+ SATI_SEQUENCE_WRITE_AND_VERIFY,
+
+ SATI_SEQUENCE_START_STOP_UNIT,
+
+ SATI_SEQUENCE_REASSIGN_BLOCKS,
+
+ // SCSI Task Requests sequences
+
+ SATI_SEQUENCE_LUN_RESET,
+ SATI_SEQUENCE_ABORT_TASK_SET,
+
+ SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS,
+ SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE,
+
+ SATI_SEQUENCE_WRITE_LONG,
+
+ SATI_SEQUENCE_UNMAP,
+
+ SATI_SEQUENCE_ATA_PASSTHROUGH_12,
+ SATI_SEQUENCE_ATA_PASSTHROUGH_16,
+
+ SATI_SEQUENCE_READ_BUFFER,
+ SATI_SEQUENCE_WRITE_BUFFER,
+ SATI_SEQUENCE_WRITE_BUFFER_MICROCODE
+
+} SATI_TRANSLATOR_SEQUENCE_TYPE;
+
+#define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6
+#define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16
+
+/**
+ * @name SATI_SEQUENCE_STATES
+ *
+ * These constants depict the various state values associated with a
+ * translation sequence.
+ */
+/*@{*/
+#define SATI_SEQUENCE_STATE_INITIAL 0
+#define SATI_SEQUENCE_STATE_TRANSLATE_DATA 1
+#define SATI_SEQUENCE_STATE_AWAIT_RESPONSE 2
+#define SATI_SEQUENCE_STATE_FINAL 3
+#define SATI_SEQUENCE_STATE_INCOMPLETE 4
+#define SATI_SEQUENCE_STATE_READ_ERROR 5
+/*@}*/
+
+/**
+ * @name SATI_DATA_DIRECTIONS
+ *
+ * These constants depict the various types of data directions for a
+ * translation sequence. Data can flow in/out (read/write) or no data at
+ * all.
+ */
+/*@{*/
+#define SATI_DATA_DIRECTION_NONE 0
+#define SATI_DATA_DIRECTION_IN 1
+#define SATI_DATA_DIRECTION_OUT 2
+/*@}*/
+
+/**
+ * @struct SATI_MODE_SELECT_PROCESSING_STATE
+ *
+ * @brief This structure contains all of the current processing states
+ * for processing mode select 6 and 10 commands' parameter fields.
+ */
+typedef struct SATI_MODE_SELECT_PROCESSING_STATE
+{
+ U8 * mode_pages;
+ U32 mode_page_offset;
+ U32 mode_pages_size;
+ U32 size_of_data_processed;
+ U32 total_ata_command_sent;
+ U32 ata_command_sent_for_cmp; // cmp: current mode page
+ BOOL current_mode_page_processed;
+
+} SATI_MODE_SELECT_PROCESSING_STATE_T;
+
+
+enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS
+{
+ SATI_REASSIGN_BLOCKS_READY_TO_SEND,
+ SATI_REASSIGN_BLOCKS_COMMAND_FAIL,
+ SATI_REASSIGN_BLOCKS_COMMAND_SUCCESS,
+};
+
+/**
+ * @struct SATI_REASSIGN_BLOCKS_PROCESSING_STATE
+ *
+ * @brief This structure contains all of the current processing states
+ * for processing reassign block command's parameter fields.
+ */
+typedef struct SATI_REASSIGN_BLOCKS_PROCESSING_STATE
+{
+ U32 lba_offset;
+ U32 block_lists_size;
+ U8 lba_size;
+ U32 size_of_data_processed;
+ U32 ata_command_sent_for_current_lba;
+ BOOL current_lba_processed;
+ enum SATI_REASSIGN_BLOCKS_ATA_COMMAND_STATUS ata_command_status;
+
+}SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T;
+
+#define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12
+
+/**
+ * @struct SATI_ATAPI_DATA
+ *
+ * @brief The SATI_ATAPI_DATA structure is for sati atapi IO specific data.
+ */
+typedef struct SATI_ATAPI_DATA
+{
+ U8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH];
+} SATI_ATAPI_DATA_T;
+
+
+enum SATI_UNMAP_ATA_COMMAND_STATUS
+{
+ SATI_UNMAP_READY_TO_SEND,
+ SATI_UNMAP_COMMAND_FAIL,
+ SATI_UNMAP_COMMAND_SUCCESS,
+};
+
+/**
+ * @struct SATI_UNMAP_PROCESSING_STATE
+ *
+ * @brief This structure contains all of the current processing states
+ * for processing unmap command data translation.
+ */
+typedef struct SATI_UNMAP_PROCESSING_STATE
+{
+ U32 max_unmap_block_descriptors;
+ U32 current_unmap_block_descriptor_index;
+ U32 current_lba_count;
+ SATI_LBA current_lba;
+ SATI_LBA next_lba;
+ U32 max_lba_range_entries;
+ void * current_dsm_descriptor;
+ void * virtual_unmap_buffer;
+ U32 physical_unmap_buffer_low;
+ U32 physical_unmap_buffer_high;
+ void * unmap_buffer_sgl_pair;
+} SATI_UNMAP_PROCESSING_STATE_T;
+
+/**
+ * @struct SATI_TRANSLATOR_SEQUENCE
+ *
+ * @brief This structure contains all of the translation information
+ * associated with a particular request.
+ */
+typedef struct SATI_TRANSLATOR_SEQUENCE
+{
+ /**
+ * This field contains the sequence type determined by the SATI.
+ */
+ U8 type;
+
+ /**
+ * This field indicates the current state for the sequence.
+ */
+ U8 state;
+
+ /**
+ * This field indicates the data direction (none, read, or write) for
+ * the translated request.
+ */
+ U8 data_direction;
+
+ /**
+ * This field contains the SATA/ATA protocol to be utilized during
+ * the IO transfer.
+ */
+ U8 protocol;
+
+ /**
+ * This field is utilized for sequences requiring data translation.
+ * It specifies the amount of data requested by the caller from the
+ * operation. It's necessary, because at times the user requests less
+ * data than is available. Thus, we need to avoid overrunning the
+ * buffer.
+ */
+ U32 allocation_length;
+
+ /**
+ * This field specifies the amount of data that will actually be
+ * transfered across the wire for this ATA request.
+ */
+ U32 ata_transfer_length;
+
+ /**
+ * This field specifies the amount of data bytes that have been
+ * set in a translation sequence. It will be incremented every time
+ * a data byte has been set by a sati translation.
+ */
+ U16 number_data_bytes_set;
+
+ /**
+ * This field indicates whether or not the sense response has been set
+ * by the translation sequence.
+ */
+ BOOL is_sense_response_set;
+
+ /**
+ * This field indicates whether or not the translation requires
+ * response translation.
+ */
+ BOOL is_translate_response_required;
+
+ /**
+ * This field specifies the remote device context for which this
+ * translator sequence is destined.
+ */
+ SATI_DEVICE_T * device;
+
+ /**
+ * This field is utilized to provide the translator with memory space
+ * required for translations that utilize multiple requests.
+ */
+ union {
+ U32 translated_command;
+ U32 move_sector_count;
+ U32 scratch;
+ SATI_REASSIGN_BLOCKS_PROCESSING_STATE_T reassign_blocks_process_state;
+ SATI_MODE_SELECT_PROCESSING_STATE_T process_state;
+ SATI_UNMAP_PROCESSING_STATE_T unmap_process_state;
+ SATI_ATAPI_DATA_T sati_atapi_data;
+ } command_specific_data;
+
+} SATI_TRANSLATOR_SEQUENCE_T;
+
+
+
+#endif // _SATI_TRANSLATOR_SEQUENCE_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_types.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_types.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,152 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_TYPES_H_
+#define _SATI_TYPES_H_
+
+/**
+ * @file
+ * @brief This file contains various type definitions to be utilized with
+ * SCSI to ATA Translation Implementation.
+ */
+
+#include <dev/isci/types.h>
+
+/**
+ * @enum _SATI_STATUS
+ *
+ * @brief This enumeration defines the possible return values from the
+ * SATI translation methods.
+ */
+typedef enum _SATI_STATUS
+{
+ /**
+ * This indicates that the translation was supported and occurred
+ * without error.
+ */
+ SATI_SUCCESS,
+
+ /**
+ * This indicates that the translation was supported and occurred
+ * without error.
+ * Additionally, this indicates the translation actually already
+ * translated the scatter gather list elements appropriately as
+ * well.
+ */
+ SATI_SUCCESS_SGL_TRANSLATED,
+
+ /**
+ * This indicates that the translation was supported, occurred without
+ * error, and no additional translation is necessary. This is done in
+ * conditions where the SCSI command doesn't require any interaction with
+ * the remote device.
+ */
+ SATI_COMPLETE,
+
+ /**
+ * This indicated everything SATI_COMPLETE does in addition to the response data
+ not using all the memory allocated by the OS.
+ */
+ SATI_COMPLETE_IO_DONE_EARLY,
+
+ /**
+ * This indicates that translator sequence has finished some specific
+ * command in the sequence, but additional commands are necessary.
+ */
+ SATI_SEQUENCE_INCOMPLETE,
+
+ /**
+ * This indicates a general failure has occurred for which no further
+ * specification information is available.
+ */
+ SATI_FAILURE,
+
+ /**
+ * This indicates that the result of the IO request indicates a
+ * failure. The caller should reference the corresponding response
+ * data for further details.
+ */
+ SATI_FAILURE_CHECK_RESPONSE_DATA,
+
+ /**
+ * This status indicates that the supplied sequence type doesn't map
+ * to an existing definition.
+ */
+ SATI_FAILURE_INVALID_SEQUENCE_TYPE,
+
+ /**
+ * This status indicates that the supplied sequence state doesn't match
+ * the operation being requested by the user.
+ */
+ SATI_FAILURE_INVALID_STATE
+
+} SATI_STATUS;
+
+#if ( !defined(DISABLE_SATI_MODE_SENSE) \
+ || !defined(DISABLE_SATI_MODE_SELECT) \
+ || !defined(DISABLE_SATI_REQUEST_SENSE) ) \
+
+#if !defined(ENABLE_SATI_MODE_PAGES)
+/**
+ * This macro enables the common mode page data structures and code.
+ * Currently, MODE SENSE, MODE SELECT, and REQUEST SENSE all make
+ * reference to this common code. As a result, enable the common
+ * mode page code if any of these 3 are being translated.
+ */
+#define ENABLE_SATI_MODE_PAGES
+#endif // !defined(ENABLE_SATI_MODE_PAGES)
+
+#endif // MODE_SENSE/SELECT/REQUEST_SENSE
+
+#endif // _SATI_TYPES_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_unmap.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_unmap.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,609 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI unmap command.
+ */
+
+#if !defined(DISABLE_SATI_UNMAP)
+
+#include <dev/isci/scil/sati_unmap.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method translates a given number of DSM
+ * requests into DSM blocks based on the devices logical block size
+ *
+ * @return Number of DSM blocks required for the DSM descriptor count
+ */
+U32 sati_unmap_calculate_dsm_blocks(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U32 dsm_descriptor_count
+)
+{
+ U32 blocks = (dsm_descriptor_count * sizeof(TRIM_PAIR))/sequence->device->logical_block_size;
+ if ((dsm_descriptor_count * sizeof(TRIM_PAIR)) % sequence->device->logical_block_size)
+ {
+ blocks++;
+ }
+ return blocks;
+}
+
+/**
+ * @brief This method performs the SCSI Unmap command translation
+ * functionality.
+ * This includes:
+ * - setting the command register
+ * - setting the device head register
+ * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_unmap_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count
+)
+{
+ U8 * h2d_register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+ U8 * d2h_register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+ sati_set_ata_command(h2d_register_fis, ATA_DATA_SET_MANAGEMENT);
+ sati_set_ata_features(h2d_register_fis, 0x01);
+ sati_set_ata_sector_count(h2d_register_fis, (U8)sector_count);
+ sati_set_ata_device_head(h2d_register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);
+
+ // Set the completion status since the core will not do that for
+ // the udma fast path.
+ sati_set_ata_status(d2h_register_fis, 0x00);
+
+ // Set up the direction and protocol for SCIC
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+ sequence->protocol = SAT_PROTOCOL_UDMA_DATA_OUT;
+ // The UNMAP translation will always require a callback
+ // on every response so it can free memory if an error
+ // occurs.
+ sequence->is_translate_response_required = TRUE;
+
+ ASSERT(sector_count < 0x100);
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method updates the unmap sequence state to the next
+ * unmap descriptor
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+SATI_STATUS sati_unmap_load_next_descriptor(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ U32 index;
+ U8 unmap_block_descriptor[16];
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Load the next descriptor
+ for(index = unmap_process_state->current_unmap_block_descriptor_index;
+ index < unmap_process_state->current_unmap_block_descriptor_index +
+ SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+ index++)
+ {
+ sati_get_data_byte(sequence,
+ scsi_io,
+ index,
+ &unmap_block_descriptor[index-unmap_process_state->current_unmap_block_descriptor_index]);
+ }
+
+ // Update the internal state for the next translation pass
+ unmap_process_state->current_lba_count = (unmap_block_descriptor[8] << 24) |
+ (unmap_block_descriptor[9] << 16) |
+ (unmap_block_descriptor[10] << 8) |
+ (unmap_block_descriptor[11]);
+ unmap_process_state->current_lba = ((SATI_LBA)(unmap_block_descriptor[0]) << 56) |
+ ((SATI_LBA)(unmap_block_descriptor[1]) << 48) |
+ ((SATI_LBA)(unmap_block_descriptor[2]) << 40) |
+ ((SATI_LBA)(unmap_block_descriptor[3]) << 32) |
+ ((SATI_LBA)(unmap_block_descriptor[4]) << 24) |
+ ((SATI_LBA)(unmap_block_descriptor[5]) << 16) |
+ ((SATI_LBA)(unmap_block_descriptor[6]) << 8) |
+ ((SATI_LBA)(unmap_block_descriptor[7]));
+ unmap_process_state->next_lba = 0;
+
+ // Update the index for the next descriptor to translate
+ unmap_process_state->current_unmap_block_descriptor_index += SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+
+ return SATI_SUCCESS;
+}
+
+/**
+ * @brief This method determines the max number of blocks of DSM data
+ * that can be satisfied by the device and the SW
+ *
+ * @return Number of blocks supported
+ * @retval Number of blocks supported
+ */
+U32 sati_unmap_get_max_buffer_size_in_blocks(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ // Currently this SATI implementation only supports a single
+ // 4k block of memory for the DMA write operation for simplicity
+ // (no need to handle more than one SG element).
+ // Since most run time UNMAP requests use 1K or less buffer space,
+ // there is no performance degradation with only supporting a
+ // single physical page. For best results allocate the maximum
+ // amount of memory the device can handle up to the maximum of 4K.
+ return MIN(SATI_DSM_MAX_BUFFER_SIZE/sequence->device->logical_block_size,
+ sequence->device->max_lba_range_entry_blocks);
+}
+
+/**
+ * @brief This method will be called before starting the first unmap translation
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful and no further processing.
+ * @retval SATI_COMPLETE - The initial processing was completed successfully
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA - Failed the initial processing
+ */
+SATI_STATUS sati_unmap_initial_processing(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ U8 * cdb;
+ U16 unmap_length;
+ U32 descriptor_length;
+ U32 index;
+ U32 max_dsm_blocks;
+ U8 unmap_param_list[8];
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Set up the sequence type for unmap translation
+ sequence->type = SATI_SEQUENCE_UNMAP;
+
+ // Make sure the device is TRIM capable
+ if ((sequence->device->capabilities & SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
+ != SATI_DEVICE_CAP_DSM_TRIM_SUPPORT)
+ {
+ // Can't send TRIM request to device that does not support it
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // get the amount of data being sent from the cdb
+ cdb = sati_cb_get_cdb_address(scsi_io);
+ unmap_length = (sati_get_cdb_byte(cdb, 7) << 8) | sati_get_cdb_byte(cdb, 8);
+
+ // If nothing has been requested return success now.
+ if (unmap_length == 0)
+ {
+ // SAT: This is not an error
+ return SATI_SUCCESS;
+ }
+ if (unmap_length < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST)
+ {
+ // Not enough length specified in the CDB
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ sequence->allocation_length = unmap_length;
+
+ // Get the unmap parameter header
+ for(index = 0; index < SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST; index++)
+ {
+ sati_get_data_byte(sequence, scsi_io, index, &unmap_param_list[index]);
+ }
+ descriptor_length = (unmap_param_list[2] << 8) | unmap_param_list[3];
+
+ // Check length again
+ if (descriptor_length == 0)
+ {
+ // SAT: This is not an error
+ return SATI_SUCCESS;
+ }
+
+ if ((U32)(unmap_length - SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST) < descriptor_length)
+ {
+ // Not enough length specified in the CDB
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // Save the maximum unmap block descriptors in this request
+ unmap_process_state->max_unmap_block_descriptors =
+ descriptor_length/SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR;
+
+ // Determine the maximum size of the write buffer that will be required
+ // for the translation in terms of number of blocks
+ max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
+
+ // Save the maximum number of DSM descriptors we can send during the translation
+ unmap_process_state->max_lba_range_entries =
+ (max_dsm_blocks*sequence->device->logical_block_size)/sizeof(TRIM_PAIR);
+
+ // Get the write buffer for the translation
+ sati_cb_allocate_dma_buffer(
+ scsi_io,
+ max_dsm_blocks*sequence->device->logical_block_size,
+ &(unmap_process_state->virtual_unmap_buffer),
+ &(unmap_process_state->physical_unmap_buffer_low),
+ &(unmap_process_state->physical_unmap_buffer_high));
+
+ // Makes sure we have a buffer
+ if (unmap_process_state->virtual_unmap_buffer == NULL)
+ {
+ // Resource failure
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ // Get the first SGL entry. This code will only use one 4K page so will
+ // only utilize the first sge.
+ sati_cb_sgl_next_sge(scsi_io,
+ ata_io,
+ NULL,
+ &(unmap_process_state->unmap_buffer_sgl_pair));
+
+ // Load the first descriptor to start the translation loop
+ unmap_process_state->current_unmap_block_descriptor_index =
+ SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST;
+ sati_unmap_load_next_descriptor(sequence,scsi_io);
+
+ // Next state will be incomplete since translation
+ // will require a callback and possibly more requests.
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+
+ return SATI_COMPLETE;
+}
+
+/**
+ * @brief This method will process each unmap sequence.
+ *
+ * @return Indicate if the translation was successful.
+ * @retval SATI_SUCCESS
+ */
+SATI_STATUS sati_unmap_process(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ SATI_LBA dsm_descriptor_lba_count;
+ U32 dsm_descriptor;
+ U32 dsm_bytes;
+ U32 dsm_remainder_bytes;
+ U32 dsm_blocks;
+ U32 max_dsm_blocks;
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Set up the starting address of the buffer for this portion of the translation
+ unmap_process_state->current_dsm_descriptor = unmap_process_state->virtual_unmap_buffer;
+ dsm_descriptor = 0;
+
+ // Translate as much as we can
+ while ((dsm_descriptor < unmap_process_state->max_lba_range_entries) &&
+ (unmap_process_state->current_lba_count > 0)) {
+ // See if the LBA count will fit in to a single descriptor
+ if (unmap_process_state->current_lba_count > SATI_DSM_MAX_SECTOR_COUNT) {
+ // Can't fit all of the lbas for this descriptor in to
+ // one DSM request. Adjust the current LbaCount and total
+ // remaining for the next descriptor
+ dsm_descriptor_lba_count = SATI_DSM_MAX_SECTOR_COUNT;
+ unmap_process_state->current_lba_count -= SATI_DSM_MAX_SECTOR_COUNT;
+ unmap_process_state->next_lba =
+ unmap_process_state->current_lba + SATI_DSM_MAX_SECTOR_COUNT;
+ } else {
+ // It all fits in to one descriptor
+ dsm_descriptor_lba_count = unmap_process_state->current_lba_count;
+ unmap_process_state->current_lba_count = 0;
+ }
+
+ // Fill in the ATA DSM descriptor
+ ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_address =
+ unmap_process_state->current_lba;
+ ((PTRIM_PAIR)(unmap_process_state->current_dsm_descriptor))->sector_count =
+ dsm_descriptor_lba_count;
+
+ // See if we can move on to the next descriptor
+ if (unmap_process_state->current_lba_count == 0) {
+ // See if there is another descriptor
+ --unmap_process_state->max_unmap_block_descriptors;
+ if (unmap_process_state->max_unmap_block_descriptors > 0) {
+ // Move on to the next descriptor
+ sati_unmap_load_next_descriptor(sequence,scsi_io);
+ }
+ } else {
+ // Move to the next LBA in this descriptor
+ unmap_process_state->current_lba = unmap_process_state->next_lba;
+ }
+
+ // Make sure the LBA does not exceed 48 bits...
+ ASSERT(unmap_process_state->current_lba <= SATI_DSM_MAX_SECTOR_ADDRESS);
+
+ // Increment the number of descriptors used and point to the next entry
+ dsm_descriptor++;
+ unmap_process_state->current_dsm_descriptor =
+ (U8 *)(unmap_process_state->current_dsm_descriptor) + sizeof(TRIM_PAIR);
+ }
+
+ // Calculate number of blocks we have filled in
+ dsm_blocks = sati_unmap_calculate_dsm_blocks(sequence,dsm_descriptor);
+ dsm_bytes = dsm_blocks * sequence->device->logical_block_size;
+ max_dsm_blocks = sati_unmap_get_max_buffer_size_in_blocks(sequence);
+
+ // The current_dsm_descriptor points to the next location in the buffer
+ // Get the remaining bytes from the last translated descriptor
+ // to the end of the 4k buffer.
+ dsm_remainder_bytes = sequence->device->logical_block_size;
+ dsm_remainder_bytes -= (U32)((POINTER_UINT)unmap_process_state->current_dsm_descriptor &
+ (sequence->device->logical_block_size-1));
+
+ // If there was no remainder, the complete buffer was filled in.
+ if (dsm_remainder_bytes != sequence->device->logical_block_size)
+ {
+ // Add on the remaining unfilled blocks
+ dsm_remainder_bytes += (sequence->device->logical_block_size * (max_dsm_blocks - dsm_blocks));
+
+ // According to ATA-8, if the DSM buffer is not completely filled with
+ // valid DSM descriptor data, the remaining portion of the
+ // buffer must be filled in with zeros.
+ memset((U8 *)unmap_process_state->current_dsm_descriptor, 0, dsm_remainder_bytes);
+ }
+
+ // Tell scic to utilize this sgl pair for write DMA processing of
+ // the SCSI UNMAP translation with the total number of bytes for this transfer
+ sati_cb_sge_write(unmap_process_state->unmap_buffer_sgl_pair,
+ unmap_process_state->physical_unmap_buffer_low,
+ unmap_process_state->physical_unmap_buffer_high,
+ dsm_bytes);
+
+ // Construct the unmap ATA request
+ sati_unmap_construct(sequence,
+ scsi_io,
+ ata_io,
+ dsm_blocks);
+
+ // Determine sequence next state based on whether there is more translation
+ // to complete
+ if (unmap_process_state->current_lba_count == 0)
+ {
+ // used for completion routine to determine if there is more processing
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ }
+ // This requests has already translated the SGL, have SCIC skip SGL translataion
+ return SATI_SUCCESS_SGL_TRANSLATED;
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will handle termination of the
+ * SCSI unmap translation and frees previously allocated
+ * dma buffer.
+ *
+ * @return None
+ */
+void sati_unmap_terminate(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ if (unmap_process_state->virtual_unmap_buffer != NULL)
+ {
+ sati_cb_free_dma_buffer(scsi_io, unmap_process_state->virtual_unmap_buffer);
+ unmap_process_state->virtual_unmap_buffer = NULL;
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI Unmap command
+ * into corresponding ATA commands. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * Additionally, in some cases more than a single ATA command may
+ * be required.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ * successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the parameter data fields.
+ */
+SATI_STATUS sati_unmap_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ // Determine if this is the first step in the unmap sequence
+ if ( sequence->state == SATI_SEQUENCE_STATE_INITIAL )
+ {
+ status = sati_unmap_initial_processing(sequence,scsi_io,ata_io);
+ if (status != SATI_COMPLETE)
+ {
+ return status;
+ }
+ }
+ // Translate the next portion of the UNMAP request
+ return sati_unmap_process(sequence, scsi_io, ata_io);
+}
+
+/**
+ * @brief This method will translate the ATA command register FIS
+ * response into an appropriate SCSI response for Unmap.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_response().
+ *
+ * @return Indicate if the response translation succeeded.
+ * @retval SATI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_COMPLETE This is returned if the command translation was
+ * successful and no ATA commands need to be set.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the parameter data fields.
+ */
+SATI_STATUS sati_unmap_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ SATI_UNMAP_PROCESSING_STATE_T * unmap_process_state;
+ SATI_STATUS sati_status = SATI_COMPLETE;
+
+ unmap_process_state = &sequence->command_specific_data.unmap_process_state;
+
+ if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ // All done, terminate the translation
+ sati_unmap_terminate(sequence, scsi_io, ata_io);
+ }
+ else
+ {
+ if (sequence->state != SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ // All done, terminate the translation
+ sati_unmap_terminate(sequence, scsi_io, ata_io);
+ }
+ else
+ {
+ // Still translating
+ sati_status = SATI_SEQUENCE_STATE_INCOMPLETE;
+ }
+ }
+ return sati_status;
+}
+
+#endif // !defined(DISABLE_SATI_UNMAP)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_unmap.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_unmap.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,135 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_UNMAP_H_
+#define _SATI_UNMAP_H_
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI reassign blocks command.
+ */
+
+#if !defined(DISABLE_SATI_UNMAP)
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_DSM_MAX_SECTOR_COUNT 0xFFFF
+#define SATI_DSM_MAX_SECTOR_ADDRESS 0xFFFFFFFFFFFF
+#define SATI_DSM_MAX_BUFFER_SIZE 4096
+
+#define SATI_UNMAP_SIZEOF_SCSI_UNMAP_BLOCK_DESCRIPTOR 16
+#define SATI_UNMAP_SIZEOF_SCSI_UNMAP_PARAMETER_LIST 8
+
+typedef struct _TRIM_PAIR
+{
+ U64 sector_address:48;
+ U64 sector_count:16;
+} TRIM_PAIR, *PTRIM_PAIR;
+
+U32 sati_unmap_calculate_dsm_blocks(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U32 dsm_descriptor_count
+);
+
+SATI_STATUS sati_unmap_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count
+);
+
+SATI_STATUS sati_unmap_load_next_descriptor(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+);
+
+U32 sati_unmap_get_max_buffer_size_in_blocks(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+SATI_STATUS sati_unmap_initial_processing(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_unmap_process(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_unmap_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_unmap_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+void sati_unmap_terminate(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+#else // !defined(DISABLE_SATI_UNMAP)
+#define sati_unmap_terminate(sequence,scsi_io,ata_io)
+#endif // !defined(DISABLE_SATI_UNMAP)
+
+#endif // _SATI_UNMAP_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_util.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_util.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,2005 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains all of the method implementations that
+ * provide generic support for SATI. Some methods can be utilized
+ * by a user to construct ATA/ATAPI commands, copy ATA device
+ * structure data, fill in sense data, etc.
+ */
+
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/intel_sas.h>
+
+/**
+ * @brief This method will set the data direction, protocol, and transfer
+ * kength for an ATA non-data command.
+ *
+ * @pre It is expected that the user will use this method for setting these
+ * values in a non-data ATA command constuct.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the IDENTIFY DEVICE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_non_data_command(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+ sequence->protocol = SAT_PROTOCOL_NON_DATA;
+ sequence->ata_transfer_length = 0;
+}
+
+/**
+ * @brief This method will construct the ATA identify device command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the IDENTIFY DEVICE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_identify_device_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_IDENTIFY_DEVICE);
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+ sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
+ sequence->ata_transfer_length = sizeof(ATA_IDENTIFY_DEVICE_DATA_T);
+}
+
+/**
+* @brief This method will construct the ATA Execute Device Diagnostic command.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+* for which to build the IDENTIFY DEVICE command.
+* @param[in] sequence This parameter specifies the translator sequence
+* for which the command is being constructed.
+*
+* @return none.
+*/
+void sati_ata_execute_device_diagnostic_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_EXECUTE_DEVICE_DIAG);
+
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+ sequence->protocol = SAT_PROTOCOL_DEVICE_DIAGNOSTIC;
+ sequence->ata_transfer_length = 16;
+}
+
+/**
+ * @brief This method will set data bytes in the user data area. If the
+ * caller requests it, the data written will be forced to ascii
+ * printable characters if it isn't already a printable character.
+ * A printable character is considered to be >= 0x20 and <= 0x70.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to copy and swap the data.
+ * @param[out] destination_scsi_io This parameter specifies the SCSI IO
+ * request containing the destination buffer into which to copy.
+ * @param[in] destination_offset This parameter specifies the offset into
+ * the data buffer where the information will be copied to.
+ * @param[in] source_value This parameter specifies the value retrieved
+ * from the source buffer that is to be copied into the user
+ * buffer area.
+ * @param[in] use_printable_chars This parameter indicates if the copy should
+ * ensure that the value copied is considered an ASCII printable
+ * character (e.g. A, B, " ", etc.). These characters reside
+ * in the 0x20 - 0x7E ASCII range.
+ *
+ * @return none
+ */
+static
+void sati_set_ascii_data_byte(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * destination_scsi_io,
+ U32 destination_offset,
+ U8 source_value,
+ BOOL use_printable_chars
+)
+{
+ // if the user requests that the copied data be ascii printable, then
+ // default to " " (i.e. 0x20) for all non-ascii printable characters.
+ if((use_printable_chars == TRUE)
+ && ((source_value < 0x20) || (source_value > 0x7E)))
+ {
+ source_value = 0x20;
+ }
+
+ sati_set_data_byte(
+ sequence, destination_scsi_io, destination_offset, source_value
+ );
+}
+
+/**
+ * @brief This method performs a copy operation using an offset into the
+ * source buffer, an offset into the destination buffer, and a length.
+ * It will perform the byte swap from the 16-bit identify field
+ * into the network byte order SCSI location.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to copy and swap the data.
+ * @param[out] destination_scsi_io This parameter specifies the SCSI IO
+ * request containing the destination buffer into which to copy.
+ * @param[in] destination_offset This parameter specifies the offset into
+ * the data buffer where the information will be copied to.
+ * @param[in] source_buffer This parameter specifies the source buffer from
+ * which the data will be copied.
+ * @param[in] source_offset This parameter specifies the offset into the
+ * source buffer where the copy shall begin.
+ * @param[in] length This parameter specifies the number of bytes to copy
+ * during this operation.
+ * @param[in] use_printable_chars This parameter indicates if the copy should
+ * ensure that the value copied is considered an ASCII printable
+ * character (e.g. A, B, " ", etc.). These characters reside
+ * in the 0x20 - 0x7E ASCII range.
+ *
+ * @return none
+ */
+void sati_ata_identify_device_copy_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * destination_scsi_io,
+ U32 destination_offset,
+ U8 * source_buffer,
+ U32 source_offset,
+ U32 length,
+ BOOL use_printable_chars
+)
+{
+ source_buffer += source_offset;
+ while (length > 0)
+ {
+ sati_set_ascii_data_byte(
+ sequence,
+ destination_scsi_io,
+ destination_offset,
+ *(source_buffer+1),
+ use_printable_chars
+ );
+
+ sati_set_ascii_data_byte(
+ sequence,
+ destination_scsi_io,
+ destination_offset+1,
+ *source_buffer,
+ use_printable_chars
+ );
+
+ destination_offset += 2;
+ source_buffer += 2;
+ length -= 2;
+ }
+}
+
+/**
+ * @brief This method performs a copy operation using a source buffer,
+ * an offset into the destination buffer, and a length.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to copy and swap the data.
+ * @param[out] destination_scsi_io This parameter specifies the SCSI IO
+ * request containing the destination buffer into which to copy.
+ * @param[in] destination_offset This parameter specifies the offset into
+ * the data buffer where the information will be copied to.
+ * @param[in] source_buffer This parameter specifies the source buffer from
+ * which the data will be copied.
+ * @param[in] length This parameter specifies the number of bytes to copy
+ * during this operation.
+ *
+ * @return none
+ */
+void sati_copy_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * destination_scsi_io,
+ U32 destination_offset,
+ U8 * source_buffer,
+ U32 length
+)
+{
+ while (length > 0)
+ {
+ sati_set_data_byte(
+ sequence, destination_scsi_io, destination_offset, *source_buffer
+ );
+
+ destination_offset++;
+ source_buffer++;
+ length--;
+ }
+}
+
+/**
+ * @brief This method extracts the Logical Block Address high and low 32-bit
+ * values and the sector count 32-bit value from the ATA identify
+ * device data.
+ *
+ * @param[in] identify This parameter specifies the ATA_IDENTIFY_DEVICE_DATA
+ * from which to extract the sector information.
+ * @param[out] lba_high This parameter specifies the upper 32 bits for the
+ * number of logical block addresses for the device. The upper
+ * 16-bits should always be 0, since 48-bits of LBA is the most
+ * supported by an ATA device.
+ * @param[out] lba_low This parameter specifies the lower 32 bits for the
+ * number of logical block addresses for the device.
+ * @param[out] sector_size This parameter specifies the 32-bits of sector
+ * size. If the ATA device doesn't support reporting it's
+ * sector size, then 512 bytes is utilized as the default value.
+ *
+ * @return none
+ */
+void sati_ata_identify_device_get_sector_info(
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 * lba_high,
+ U32 * lba_low,
+ U32 * sector_size
+)
+{
+ // Calculate the values to be returned
+ // Calculation will be different if the SATA device supports
+ // 48-bit addressing. Bit 10 of Word 86 of ATA Identify
+ if (identify->command_set_enabled1
+ & ATA_IDENTIFY_COMMAND_SET_SUPPORTED1_48BIT_ENABLE)
+ {
+ // This drive supports 48-bit addressing
+
+ *lba_high = identify->max_48bit_lba[7] << 24;
+ *lba_high |= identify->max_48bit_lba[6] << 16;
+ *lba_high |= identify->max_48bit_lba[5] << 8;
+ *lba_high |= identify->max_48bit_lba[4];
+
+ *lba_low = identify->max_48bit_lba[3] << 24;
+ *lba_low |= identify->max_48bit_lba[2] << 16;
+ *lba_low |= identify->max_48bit_lba[1] << 8;
+ *lba_low |= identify->max_48bit_lba[0];
+ }
+ else
+ {
+ // This device doesn't support 48-bit addressing
+ // Pull out the largest LBA from words 60 and 61.
+ *lba_high = 0;
+ *lba_low = identify->total_num_sectors[3] << 24;
+ *lba_low |= identify->total_num_sectors[2] << 16;
+ *lba_low |= identify->total_num_sectors[1] << 8;
+ *lba_low |= identify->total_num_sectors[0];
+ }
+
+ // If the ATA device reports its sector size (bit 12 of Word 106),
+ // then use that instead.
+ if (identify->physical_logical_sector_info
+ & ATA_IDENTIFY_SECTOR_LARGER_THEN_512_ENABLE)
+ {
+ *sector_size = identify->words_per_logical_sector[3] << 24;
+ *sector_size |= identify->words_per_logical_sector[2] << 16;
+ *sector_size |= identify->words_per_logical_sector[1] << 8;
+ *sector_size |= identify->words_per_logical_sector[0];
+ }
+ else
+ {
+ // Default the sector size to 512 bytes
+ *sector_size = 512;
+ }
+}
+
+/**
+ * @brief This method will construct the ATA check power mode command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the CHECK POWER MODE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_check_power_mode_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_CHECK_POWER_MODE);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method is utilized to set a specific byte in the sense
+ * data area. It will ensure that the supplied byte offset
+ * isn't larger then the length of the requested sense data.
+ *
+ * @param[in] scsi_io This parameter specifies the user SCSI IO request
+ * for which to set the sense data byte.
+ * @param[in] byte_offset This parameter specifies the byte offset into
+ * the sense data buffer where the data should be written.
+ * @param[in] value This parameter specifies the 8-bit value to be written
+ * into the sense data area.
+ *
+ * @return none
+ */
+void sati_set_sense_data_byte(
+ U8 * sense_data,
+ U32 max_sense_data_len,
+ U32 byte_offset,
+ U8 value
+)
+{
+ // Ensure that we don't attempt to write past the end of the sense
+ // data buffer.
+ if (byte_offset < max_sense_data_len)
+ sense_data[byte_offset] = value;
+}
+
+/**
+ * @brief This method will construct the common response IU in the user
+ * request's response IU location.
+ *
+ * @param[out] rsp_iu This parameter specifies the user request's
+ * response IU to be constructed.
+ * @param[in] scsi_status This parameter specifies the SCSI status
+ * value for the user's IO request.
+ * @param[in] sense_data_length This parameter specifies the sense data
+ * length for response IU.
+ * @param[in] data_present The parameter specifies the specific
+ * data present value for response IU.
+ *
+ * @return none
+ */
+void sati_scsi_common_response_iu_construct(
+ SCI_SSP_RESPONSE_IU_T * rsp_iu,
+ U8 scsi_status,
+ U8 sense_data_length,
+ U8 data_present
+)
+{
+ rsp_iu->sense_data_length[3] = sense_data_length;
+ rsp_iu->sense_data_length[2] = 0;
+ rsp_iu->sense_data_length[1] = 0;
+ rsp_iu->sense_data_length[0] = 0;
+ rsp_iu->status = scsi_status;
+ rsp_iu->data_present = data_present;
+}
+
+/**
+ * @brief This method will construct the buffer for sense data
+ * sense data buffer location. Additionally, it will set the user's
+ * SCSI status.
+ *
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the buffer for sense data.
+ * @param[in] scsi_status This parameter specifies the SCSI status
+ * value for the user's IO request.
+ * @param[out] sense_data This paramater
+ *
+ * @return none
+ */
+static
+void sati_scsi_get_sense_data_buffer(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 scsi_status,
+ U8 ** sense_data,
+ U32 * sense_len)
+{
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+ SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
+ sati_cb_get_response_iu_address(scsi_io);
+
+ sati_scsi_common_response_iu_construct(
+ rsp_iu,
+ scsi_status,
+ sati_scsi_get_sense_data_length(sequence, scsi_io),
+ SCSI_RESPONSE_DATA_PRES_SENSE_DATA
+ );
+
+ *sense_data = (U8*) rsp_iu->data;
+ *sense_len = SSP_RESPONSE_IU_MAX_DATA * 4; // dwords to bytes
+#else
+ *sense_data = sati_cb_get_sense_data_address(scsi_io);
+ *sense_len = sati_cb_get_sense_data_length(scsi_io);
+ sati_cb_set_scsi_status(scsi_io, scsi_status);
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+}
+
+/**
+ * @brief This method extract response code based on on device settings.
+ *
+ * @return response code
+ */
+static
+U8 sati_scsi_get_sense_data_response_code(SATI_TRANSLATOR_SEQUENCE_T * sequence)
+{
+ if (sequence->device->descriptor_sense_enable)
+ {
+ return SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE;
+ }
+ else
+ {
+ return SCSI_FIXED_CURRENT_RESPONSE_CODE;
+ }
+}
+
+/**
+ * @brief This method will return length of descriptor sense data for executed command.
+ *
+ * @return sense data length
+ */
+static
+U8 sati_scsi_get_descriptor_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ //Initial value is descriptor header length
+ U8 length = 8;
+
+ switch (sati_get_cdb_byte(cdb, 0))
+ {
+#if !defined(DISABLE_SATI_WRITE_LONG)
+ case SCSI_WRITE_LONG_10:
+ case SCSI_WRITE_LONG_16:
+ length += SCSI_BLOCK_DESCRIPTOR_LENGTH +
+ SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+ break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+ case SCSI_REASSIGN_BLOCKS:
+ length += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH +
+ SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+ break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+ case SCSI_READ_6:
+ case SCSI_READ_10:
+ case SCSI_READ_12:
+ case SCSI_READ_16:
+ case SCSI_WRITE_6:
+ case SCSI_WRITE_10:
+ case SCSI_WRITE_12:
+ case SCSI_WRITE_16:
+#if !defined(DISABLE_SATI_VERIFY)
+ case SCSI_VERIFY_10:
+ case SCSI_VERIFY_12:
+ case SCSI_VERIFY_16:
+#endif // !defined(DISABLE_SATI_VERIFY)
+#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \
+ && !defined(DISABLE_SATI_VERIFY) \
+ && !defined(DISABLE_SATI_WRITE)
+
+ case SCSI_WRITE_AND_VERIFY_10:
+ case SCSI_WRITE_AND_VERIFY_12:
+ case SCSI_WRITE_AND_VERIFY_16:
+#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+ // && !defined(DISABLE_SATI_VERIFY)
+ // && !defined(DISABLE_SATI_WRITE)
+ length += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+ break;
+ }
+
+ return length;
+}
+
+/**
+ * @brief This method will return length of sense data.
+ *
+ * @return sense data length
+ */
+U8 sati_scsi_get_sense_data_length(SATI_TRANSLATOR_SEQUENCE_T * sequence, void * scsi_io)
+{
+ U8 response_code;
+
+ response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+ switch (response_code)
+ {
+ case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+ case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+ return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
+ break;
+ case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+ case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+ return sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io);
+ break;
+ }
+
+ return SCSI_FIXED_SENSE_DATA_BASE_LENGTH;
+}
+
+/**
+ * @brief This method will construct the sense data buffer in the user's
+ * sense data buffer location. Additionally, it will set the user's
+ * SCSI status.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the sense data.
+ * @param[in] scsi_status This parameter specifies the SCSI status
+ * value for the user's IO request.
+ * @param[in] sense_key This parameter specifies the sense key to
+ * be set for the user's IO request.
+ * @param[in] additional_sense_code This parameter specifies the
+ * additional sense code (ASC) key to be set for the user's
+ * IO request.
+ * @param[in] additional_sense_code_qualifier This parameter specifies
+ * the additional sense code qualifier (ASCQ) key to be set
+ * for the user's IO request.
+ *
+ * @return none
+ */
+void sati_scsi_sense_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 scsi_status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 response_code;
+
+ response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+ switch (response_code)
+ {
+ case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+ case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+ sati_scsi_fixed_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
+ sense_key, additional_sense_code, additional_sense_code_qualifier);
+ break;
+ case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+ case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+ sati_scsi_descriptor_sense_data_construct(sequence, scsi_io, scsi_status, response_code,
+ sense_key, additional_sense_code, additional_sense_code_qualifier);
+ break;
+ }
+
+ sequence->is_sense_response_set = TRUE;
+}
+
+/**
+ * @brief This method will construct the block descriptor in the user's descriptor
+ * sense data buffer location.
+ *
+ * @param[in] sense_data This parameter specifies the user SCSI IO request
+ * for which to set the sense data byte.
+ * @param[in] sense_len This parameter specifies length of the sense data
+ * to be returned by SATI.
+ * @param[out] descriptor_len This parameter returns the length of constructed
+ * descriptor.
+ *
+ * @return none
+ */
+static
+void sati_scsi_block_descriptor_construct(
+ U8 * sense_data,
+ U32 sense_len)
+{
+ U8 ili = 1;
+
+ sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_BLOCK_DESCRIPTOR_TYPE);
+ sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_BLOCK_DESCRIPTOR_ADDITIONAL_LENGTH);
+ sati_set_sense_data_byte(sense_data, sense_len, 2, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 3, (ili << 5));
+}
+
+/**
+ * @brief This method will construct the command-specific descriptor for
+ * the descriptor sense data buffer in the user's sense data buffer
+ * location.
+ *
+ * @param[in] sense_data This parameter specifies the user SCSI IO request
+ * for which to set the sense data byte.
+ * @param[in] sense_len This parameter specifies length of the sense data
+ * to be returned by SATI.
+ * @param[out] descriptor_len This parameter returns the length of constructed
+ * descriptor.
+ * @param[in] information_buff This parameter specifies the address for which
+ * to set the command-specific information buffer.
+ *
+ * @return none
+ */
+static
+void sati_scsi_command_specific_descriptor_construct(
+ U8 * sense_data,
+ U32 sense_len,
+ U8 * information_buff)
+{
+ U8 i;
+
+ sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_CMD_SPECIFIC_DESCRIPTOR_TYPE);
+ sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_CMD_SPECIFIC_DESCRIPTOR_ADDITIONAL_LENGTH);
+ sati_set_sense_data_byte(sense_data, sense_len, 2, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 3, 0);
+
+ // fill information buffer
+ // SBC 5.20.1 REASSIGN BLOCKS command overview
+ // If information about the first LBA not reassigned is not available
+ // COMMAND-SPECIFIC INFORMATION field shall be set to FFFF_FFFF_FFFF_FFFFh
+ for (i=0; i<8; i++)
+ sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0xFF:information_buff[i]);
+}
+
+/**
+ * @brief This method will construct the information descriptor for
+ * the descriptor sense data buffer in the user's sense data buffer
+ * location.
+ *
+ * @param[in] sense_data This parameter specifies the user SCSI IO request
+ * for which to set the sense data byte.
+ * @param[in] sense_len This parameter specifies length of the sense data
+ * to be returned by SATI.
+ * @param[out] descriptor_len This parameter returns the length of constructed
+ * descriptor.
+ * @param[in] information_buff This parameter specifies the address for which
+ * to set the information buffer.
+ *
+ * @return none
+ */
+static
+void sati_scsi_information_descriptor_construct(
+ U8 * sense_data,
+ U32 sense_len,
+ U8 * information_buff)
+{
+ U8 i;
+ U8 valid = 1;
+
+ sati_set_sense_data_byte(sense_data, sense_len, 0, SCSI_INFORMATION_DESCRIPTOR_TYPE);
+ sati_set_sense_data_byte(sense_data, sense_len, 1, SCSI_INFORMATION_DESCRIPTOR_ADDITIONAL_LENGTH);
+ sati_set_sense_data_byte(sense_data, sense_len, 2, (valid << 7));
+ sati_set_sense_data_byte(sense_data, sense_len, 3, 0);
+
+ // fill information buffer
+ for (i=0; i<8; i++)
+ sati_set_sense_data_byte(sense_data, sense_len, 4 + i, information_buff==NULL?0:information_buff[i]);
+}
+
+/**
+ * @brief This method will construct the descriptors in the user's descriptor
+ * sense data buffer location.
+ *
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the sense data.
+ * @param[in] sense_data This parameter specifies the user SCSI IO request
+ * for which to set the sense data byte.
+ * @param[in] sense_len This parameter specifies length of the sense data
+ * to be returned by SATI.
+ * @param[out] descriptor_len This parameter returns the length of constructed
+ * descriptor.
+ * @param[in] information_buff This parameter specifies the address for which
+ * to set the information buffer.
+ *
+ * @return none
+ */
+static
+void sati_scsi_common_descriptors_construct(
+ void * scsi_io,
+ U8 * sense_data,
+ U32 sense_len,
+ U8 * information_buff)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 offset = 0;
+
+ switch (sati_get_cdb_byte(cdb, 0))
+ {
+#if !defined(DISABLE_SATI_WRITE_LONG)
+ case SCSI_WRITE_LONG_10:
+ case SCSI_WRITE_LONG_16:
+ sati_scsi_block_descriptor_construct(
+ sense_data + offset,
+ sense_len - offset);
+
+ offset += SCSI_BLOCK_DESCRIPTOR_LENGTH;
+ sati_scsi_information_descriptor_construct(
+ sense_data + offset,
+ sense_len - offset,
+ information_buff);
+
+ offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+ break;
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
+#if !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+ case SCSI_REASSIGN_BLOCKS:
+ sati_scsi_command_specific_descriptor_construct(
+ sense_data + offset,
+ sense_len - offset,
+ NULL);
+
+ offset += SCSI_CMD_SPECIFIC_DESCRIPTOR_LENGTH;
+ sati_scsi_information_descriptor_construct(
+ sense_data + offset,
+ sense_len - offset,
+ information_buff);
+
+ offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+ break;
+#endif // !defined(DISABLE_SATI_REASSIGN_BLOCKS)
+ case SCSI_READ_6:
+ case SCSI_READ_10:
+ case SCSI_READ_12:
+ case SCSI_READ_16:
+ case SCSI_WRITE_6:
+ case SCSI_WRITE_10:
+ case SCSI_WRITE_12:
+ case SCSI_WRITE_16:
+#if !defined(DISABLE_SATI_VERIFY)
+ case SCSI_VERIFY_10:
+ case SCSI_VERIFY_12:
+ case SCSI_VERIFY_16:
+#endif // !defined(DISABLE_SATI_VERIFY)
+#if !defined(DISABLE_SATI_WRITE_AND_VERIFY) \
+ && !defined(DISABLE_SATI_VERIFY) \
+ && !defined(DISABLE_SATI_WRITE)
+
+ case SCSI_WRITE_AND_VERIFY_10:
+ case SCSI_WRITE_AND_VERIFY_12:
+ case SCSI_WRITE_AND_VERIFY_16:
+#endif // !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+ // && !defined(DISABLE_SATI_VERIFY)
+ // && !defined(DISABLE_SATI_WRITE)
+ sati_scsi_information_descriptor_construct(
+ sense_data + offset,
+ sense_len - offset,
+ information_buff);
+
+ offset += SCSI_INFORMATION_DESCRIPTOR_LENGTH;
+ break;
+ }
+}
+
+/**
+ * @brief This method will construct the descriptor sense data buffer in
+ * the user's sense data buffer location. Additionally, it will set
+ * the user's SCSI status.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the sense data.
+ * @param[in] scsi_status This parameter specifies the SCSI status
+ * value for the user's IO request.
+ * @param[in] sense_key This parameter specifies the sense key to
+ * be set for the user's IO request.
+ * @param[in] additional_sense_code This parameter specifies the
+ * additional sense code (ASC) key to be set for the user's
+ * IO request.
+ * @param[in] additional_sense_code_qualifier This parameter specifies
+ * the additional sense code qualifier (ASCQ) key to be set
+ * for the user's IO request.
+ *
+ * @return none
+ */
+void sati_scsi_descriptor_sense_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 scsi_status,
+ U8 response_code,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 * sense_data;
+ U32 sense_len;
+
+ sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+ sati_set_sense_data_byte(
+ sense_data,
+ sense_len,
+ 0,
+ response_code
+ );
+
+ sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key);
+ sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code);
+ sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier);
+ sati_set_sense_data_byte(sense_data, sense_len, 4, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 5, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 6, 0);
+
+ sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, NULL);
+
+ sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
+}
+
+/**
+ * @brief This method will construct the fixed format sense data buffer
+ * in the user's sense data buffer location. Additionally, it will
+ * set the user's SCSI status.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the sense data.
+ * @param[in] scsi_status This parameter specifies the SCSI status
+ * value for the user's IO request.
+ * @param[in] sense_key This parameter specifies the sense key to
+ * be set for the user's IO request.
+ * @param[in] additional_sense_code This parameter specifies the
+ * additional sense code (ASC) key to be set for the user's
+ * IO request.
+ * @param[in] additional_sense_code_qualifier This parameter specifies
+ * the additional sense code qualifier (ASCQ) key to be set
+ * for the user's IO request.
+ *
+ * @return none
+ */
+void sati_scsi_fixed_sense_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 scsi_status,
+ U8 response_code,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 * sense_data;
+ U32 sense_len;
+
+ sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+ // Write out the sense data format per SPC-4.
+ // We utilize the fixed format sense data format.
+
+ sati_set_sense_data_byte(
+ sense_data,
+ sense_len,
+ 0,
+ response_code | SCSI_FIXED_SENSE_DATA_VALID_BIT
+ );
+
+ sati_set_sense_data_byte(sense_data, sense_len, 1, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key);
+ sati_set_sense_data_byte(sense_data, sense_len, 3, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 4, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 5, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 6, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 7, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 8, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 9, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
+ sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
+ sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 15, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
+}
+
+/**
+* @brief This method will construct common sense data that will be identical in
+* both read error sense construct functions.
+* sati_scsi_read_ncq_error_sense_construct,
+* sati_scsi_read_error_sense_construct
+*
+ * @param[in] sense_data This parameter specifies the user SCSI IO request
+ * for which to set the sense data byte.
+* @param[in] sense_len This parameter specifies length of the sense data
+* to be returned by SATI.
+* @param[in] sense_key This parameter specifies the sense key to
+* be set for the user's IO request.
+* @param[in] additional_sense_code This parameter specifies the
+* additional sense code (ASC) key to be set for the user's
+* IO request.
+* @param[in] additional_sense_code_qualifier This parameter specifies
+* the additional sense code qualifier (ASCQ) key to be set
+* for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_common_fixed_sense_construct(
+ U8 * sense_data,
+ U32 sense_len,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+
+ sati_set_sense_data_byte(sense_data, sense_len, 1, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 2, sense_key);
+
+ //Bytes 3, 4, 5, 6 are set in read_error_sense_construct functions
+
+ sati_set_sense_data_byte(sense_data, sense_len, 7, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 8, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 9, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 10, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 11, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 12, additional_sense_code);
+ sati_set_sense_data_byte(sense_data, sense_len, 13, additional_sense_code_qualifier);
+ sati_set_sense_data_byte(sense_data, sense_len, 14, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 15, 0x80);
+ sati_set_sense_data_byte(sense_data, sense_len, 16, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 17, 0);
+}
+
+/**
+ * @brief This method will construct the descriptor sense data buffer in
+ * the user's sense data buffer location. Additionally, it will set
+ * the user's SCSI status.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the sense data.
+ * @param[in] scsi_status This parameter specifies the SCSI status
+ * value for the user's IO request.
+ * @param[in] sense_key This parameter specifies the sense key to
+ * be set for the user's IO request.
+ * @param[in] additional_sense_code This parameter specifies the
+ * additional sense code (ASC) key to be set for the user's
+ * IO request.
+ * @param[in] additional_sense_code_qualifier This parameter specifies
+ * the additional sense code qualifier (ASCQ) key to be set
+ * for the user's IO request.
+ *
+ * @return none
+ */
+static
+void sati_scsi_common_descriptor_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 * sense_data,
+ U32 sense_len,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier,
+ U8 * information_buff
+)
+{
+ sati_set_sense_data_byte(sense_data, sense_len, 1, sense_key);
+ sati_set_sense_data_byte(sense_data, sense_len, 2, additional_sense_code);
+ sati_set_sense_data_byte(sense_data, sense_len, 3, additional_sense_code_qualifier);
+ sati_set_sense_data_byte(sense_data, sense_len, 4, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 5, 0);
+ sati_set_sense_data_byte(sense_data, sense_len, 6, 0);
+
+ sati_scsi_common_descriptors_construct(scsi_io, sense_data + 8, sense_len, information_buff);
+
+ sati_set_sense_data_byte(sense_data, sense_len, 7, sati_scsi_get_descriptor_sense_data_length(sequence, scsi_io) - 8);
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+* descriptor sense data buffer location. Additionally, it will set
+* the user's SCSI status. This is only used for NCQ uncorrectable
+* read errors
+*
+* @param[in] sequence This parameter specifies the translation sequence
+* for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+* for which to construct the sense data.
+* @param[in] ata_input_data This parameter specifies the user's ATA IO
+* response from a Read Log Ext command.
+* @param[in] scsi_status This parameter specifies the SCSI status
+* value for the user's IO request.
+* @param[in] sense_key This parameter specifies the sense key to
+* be set for the user's IO request.
+* @param[in] additional_sense_code This parameter specifies the
+* additional sense code (ASC) key to be set for the user's
+* IO request.
+* @param[in] additional_sense_code_qualifier This parameter specifies
+* the additional sense code qualifier (ASCQ) key to be set
+* for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_ncq_error_descriptor_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_input_data,
+ U8 scsi_status,
+ U8 response_code,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 * sense_data;
+ U32 sense_len;
+
+ U8 information_buff[8] = {0};
+
+ ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
+
+ sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+ sati_set_sense_data_byte(
+ sense_data,
+ sense_len,
+ 0,
+ response_code
+ );
+
+ information_buff[2] = ncq_log->lba_47_40;
+ information_buff[3] = ncq_log->lba_39_32;
+ information_buff[4] = ncq_log->lba_31_24;
+ information_buff[5] = ncq_log->lba_23_16;
+ information_buff[6] = ncq_log->lba_15_8;
+ information_buff[7] = ncq_log->lba_7_0;
+
+ sati_scsi_common_descriptor_sense_construct(
+ sequence,
+ scsi_io,
+ sense_data,
+ sense_len,
+ sense_key,
+ additional_sense_code,
+ additional_sense_code_qualifier,
+ information_buff
+ );
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+* sense data buffer location. Additionally, it will set the user's
+* SCSI status. This is only used for NCQ uncorrectable read errors
+*
+* @param[in] sequence This parameter specifies the translation sequence
+* for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+* for which to construct the sense data.
+* @param[in] ata_input_data This parameter specifies the user's ATA IO
+* response from a Read Log Ext command.
+* @param[in] scsi_status This parameter specifies the SCSI status
+* value for the user's IO request.
+* @param[in] sense_key This parameter specifies the sense key to
+* be set for the user's IO request.
+* @param[in] additional_sense_code This parameter specifies the
+* additional sense code (ASC) key to be set for the user's
+* IO request.
+* @param[in] additional_sense_code_qualifier This parameter specifies
+* the additional sense code qualifier (ASCQ) key to be set
+* for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_ncq_error_fixed_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_input_data,
+ U8 scsi_status,
+ U8 response_code,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 * sense_data;
+ U32 sense_len;
+ U8 valid = TRUE;
+
+ ATA_NCQ_COMMAND_ERROR_LOG_T * ncq_log = (ATA_NCQ_COMMAND_ERROR_LOG_T *) ata_input_data;
+
+ sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+ if(ncq_log->lba_39_32 > 0)
+ {
+ valid = FALSE;
+ }
+
+ sati_set_sense_data_byte(
+ sense_data,
+ sense_len,
+ 0,
+ (valid << 7) | response_code
+ );
+
+ sati_set_sense_data_byte(sense_data, sense_len, 3, ncq_log->lba_31_24);
+ sati_set_sense_data_byte(sense_data, sense_len, 4, ncq_log->lba_23_16);
+ sati_set_sense_data_byte(sense_data, sense_len, 5, ncq_log->lba_15_8);
+ sati_set_sense_data_byte(sense_data, sense_len, 6, ncq_log->lba_7_0);
+
+ sati_scsi_common_fixed_sense_construct(
+ sense_data,
+ sense_len,
+ sense_key,
+ additional_sense_code,
+ additional_sense_code_qualifier
+ );
+}
+
+void sati_scsi_read_ncq_error_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_input_data,
+ U8 scsi_status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 response_code;
+
+ response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+ switch (response_code)
+ {
+ case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+ case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+ sati_scsi_read_ncq_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+ response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+ break;
+ case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+ case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+ sati_scsi_read_ncq_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+ response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+ break;
+ }
+
+ sequence->is_sense_response_set = TRUE;
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+* sense data buffer location. Additionally, it will set the user's
+* SCSI status. This is used for uncorrectable read errors.
+*
+* @param[in] sequence This parameter specifies the translation sequence
+* for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+* for which to construct the sense data.
+* @param[in] ata_io This parameter is a pointer to the ATA IO data used
+* to get the ATA register fis.
+* @param[in] scsi_status This parameter specifies the SCSI status
+* value for the user's IO request.
+* @param[in] sense_key This parameter specifies the sense key to
+* be set for the user's IO request.
+* @param[in] additional_sense_code This parameter specifies the
+* additional sense code (ASC) key to be set for the user's
+* IO request.
+* @param[in] additional_sense_code_qualifier This parameter specifies
+* the additional sense code qualifier (ASCQ) key to be set
+* for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_error_descriptor_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 scsi_status,
+ U8 response_code,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 * sense_data;
+ U32 sense_len;
+ U8 information_buff[8] = {0};
+
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+ sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+ information_buff[2] = sati_get_ata_lba_high_ext(register_fis);
+ information_buff[3] = sati_get_ata_lba_mid_ext(register_fis);
+ information_buff[4] = sati_get_ata_lba_low_ext(register_fis);
+ information_buff[5] = sati_get_ata_lba_high(register_fis);
+ information_buff[6] = sati_get_ata_lba_mid(register_fis);
+ information_buff[7] = sati_get_ata_lba_low(register_fis);
+
+ sati_set_sense_data_byte(
+ sense_data,
+ sense_len,
+ 0,
+ SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE
+ );
+
+ sati_scsi_common_descriptor_sense_construct(
+ sequence,
+ scsi_io,
+ sense_data,
+ sense_len,
+ sense_key,
+ additional_sense_code,
+ additional_sense_code_qualifier,
+ information_buff
+ );
+}
+
+/**
+* @brief This method will construct the sense data buffer in the user's
+* sense data buffer location. Additionally, it will set the user's
+* SCSI status. This is used for uncorrectable read errors.
+*
+* @param[in] sequence This parameter specifies the translation sequence
+* for which to construct the sense data.
+* @param[in,out] scsi_io This parameter specifies the user's IO request
+* for which to construct the sense data.
+* @param[in] ata_io This parameter is a pointer to the ATA IO data used
+* to get the ATA register fis.
+* @param[in] scsi_status This parameter specifies the SCSI status
+* value for the user's IO request.
+* @param[in] sense_key This parameter specifies the sense key to
+* be set for the user's IO request.
+* @param[in] additional_sense_code This parameter specifies the
+* additional sense code (ASC) key to be set for the user's
+* IO request.
+* @param[in] additional_sense_code_qualifier This parameter specifies
+* the additional sense code qualifier (ASCQ) key to be set
+* for the user's IO request.
+*
+* @return none
+*/
+static
+void sati_scsi_read_error_fixed_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 scsi_status,
+ U8 response_code,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 * sense_data;
+ U32 sense_len;
+ U8 valid = TRUE;
+
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+ sati_scsi_get_sense_data_buffer(sequence, scsi_io, scsi_status, &sense_data, &sense_len);
+
+ if(sati_get_ata_lba_mid_ext(register_fis) > 0)
+ {
+ valid = FALSE;
+ }
+
+ sati_set_sense_data_byte(sense_data, sense_len, 3, sati_get_ata_lba_low_ext(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 4, sati_get_ata_lba_high(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 5, sati_get_ata_lba_mid(register_fis));
+ sati_set_sense_data_byte(sense_data, sense_len, 6, sati_get_ata_lba_low(register_fis));
+
+
+ sati_set_sense_data_byte(
+ sense_data,
+ sense_len,
+ 0,
+ (valid << 7) | SCSI_FIXED_CURRENT_RESPONSE_CODE
+ );
+
+ sati_scsi_common_fixed_sense_construct(
+ sense_data,
+ sense_len,
+ sense_key,
+ additional_sense_code,
+ additional_sense_code_qualifier
+ );
+}
+
+void sati_scsi_read_error_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_input_data,
+ U8 scsi_status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+)
+{
+ U8 response_code;
+
+ response_code = sati_scsi_get_sense_data_response_code(sequence);
+
+ switch (response_code)
+ {
+ case SCSI_FIXED_CURRENT_RESPONSE_CODE:
+ case SCSI_FIXED_DEFERRED_RESPONSE_CODE:
+ sati_scsi_read_error_fixed_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+ response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+ break;
+ case SCSI_DESCRIPTOR_CURRENT_RESPONSE_CODE:
+ case SCSI_DESCRIPTOR_DEFERRED_RESPONSE_CODE:
+ sati_scsi_read_error_descriptor_sense_construct(sequence, scsi_io, ata_input_data, scsi_status,
+ response_code, sense_key, additional_sense_code, additional_sense_code_qualifier);
+ break;
+ }
+
+ sequence->is_sense_response_set = TRUE;
+}
+
+/*
+ * @brief This method builds the scsi response data for a sata task management
+ * request.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to construct the sense data.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to construct the sense data.
+ * @param[in] response_data The response status for the task management
+ * request.
+ */
+void sati_scsi_response_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 response_data
+)
+{
+#ifdef SATI_TRANSPORT_SUPPORTS_SAS
+ SCI_SSP_RESPONSE_IU_T * rsp_iu = (SCI_SSP_RESPONSE_IU_T*)
+ sati_cb_get_response_iu_address(scsi_io);
+ rsp_iu->data_present = 0x01;
+ rsp_iu->response_data_length[3] = sizeof(U32);
+ rsp_iu->status = 0;
+ ((U8 *)rsp_iu->data)[3] = response_data;
+#else
+#endif // SATI_TRANSPORT_SUPPORTS_SAS
+}
+
+/**
+ * @brief This method checks to make sure that the translation isn't
+ * exceeding the allocation length specified in the CDB prior
+ * to retrieving the payload data byte from the user's buffer.
+ *
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to set the user payload data byte.
+ * @param[in] byte_offset This parameter specifies the offset into
+ * the user's payload buffer at which to write the supplied
+ * value.
+ * @param[in] value This parameter specifies the memory location into
+ * which to read the value from the user's payload buffer.
+ *
+ * @return none
+ */
+void sati_get_data_byte(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 byte_offset,
+ U8 * value
+)
+{
+ if (byte_offset < sequence->allocation_length)
+ sati_cb_get_data_byte(scsi_io, byte_offset, value);
+}
+
+/**
+ * @brief This method checks to make sure that the translation isn't
+ * exceeding the allocation length specified in the CDB while
+ * translating payload data into the user's buffer.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to set the user payload data byte.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to set the user payload data byte.
+ * @param[in] byte_offset This parameter specifies the offset into
+ * the user's payload buffer at which to write the supplied
+ * value.
+ * @param[in] value This parameter specifies the new value to be
+ * written out into the user's payload buffer.
+ *
+ * @return none
+ */
+void sati_set_data_byte(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 byte_offset,
+ U8 value
+)
+{
+ if (byte_offset < sequence->allocation_length)
+ {
+ sequence->number_data_bytes_set++;
+ sati_cb_set_data_byte(scsi_io, byte_offset, value);
+ }
+}
+
+/**
+ * @brief This method checks to make sure that the translation isn't
+ * exceeding the allocation length specified in the CDB while
+ * translating payload data into the user's buffer.
+ *
+ * @param[in] sequence This parameter specifies the translation sequence
+ * for which to set the user payload data dword.
+ * @param[in,out] scsi_io This parameter specifies the user's IO request
+ * for which to set the user payload data dword.
+ * @param[in] byte_offset This parameter specifies the offset into
+ * the user's payload buffer at which to write the supplied
+ * value.
+ * @param[in] value This parameter specifies the new value to be
+ * written out into the user's payload buffer.
+ *
+ * @return none
+ */
+void sati_set_data_dword(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 byte_offset,
+ U32 value
+)
+{
+ /// @todo Check to ensure that the bytes appear correctly (SAS Address).
+
+ sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)value & 0xFF);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 8) & 0xFF);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 16) & 0xFF);
+ byte_offset++;
+ sati_set_data_byte(sequence, scsi_io, byte_offset, (U8)(value >> 24) & 0xFF);
+}
+
+/**
+ * @brief This method will construct the ATA flush cache command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the FLUSH CACHE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_flush_cache_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_FLUSH_CACHE);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA standby immediate command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the STANDBY IMMEDIATE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @param[in] count This parameter specifies the time period programmed
+ * into the Standby Timer. See ATA8 spec for more details
+ * @return none.
+ */
+void sati_ata_standby_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U16 count
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_STANDBY);
+ sati_set_ata_sector_count(register_fis, count);
+
+ sequence->device->ata_standby_timer = (U8) count;
+
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA standby immediate command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the STANDBY IMMEDIATE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_standby_immediate_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_STANDBY_IMMED);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA idle immediate command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the IDLE IMMEDIATE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_idle_immediate_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
+ sati_set_ata_features(register_fis, 0x00);
+ sati_set_ata_sector_count(register_fis, 0x00);
+ sati_set_ata_lba_high(register_fis, 0x00);
+ sati_set_ata_lba_mid(register_fis, 0x00);
+ sati_set_ata_lba_low(register_fis, 0x00);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA idle immediate command
+ for Unload Features.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the IDLE IMMEDIATE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_idle_immediate_unload_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_IDLE_IMMED);
+ sati_set_ata_features(register_fis, 0x44);
+ sati_set_ata_sector_count(register_fis, 0x00);
+ sati_set_ata_lba_high(register_fis, 0x55);
+ sati_set_ata_lba_mid(register_fis, 0x4E);
+ sati_set_ata_lba_low(register_fis, 0x4C);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA IDLE command.\
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the ATA IDLE command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_idle_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_IDLE);
+ sati_set_ata_features(register_fis, 0x00);
+ sati_set_ata_sector_count(register_fis, 0x00);
+
+ sequence->device->ata_standby_timer = 0x00;
+
+ sati_set_ata_lba_high(register_fis, 0x00);
+ sati_set_ata_lba_mid(register_fis, 0x00);
+ sati_set_ata_lba_low(register_fis, 0x00);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct the ATA MEDIA EJECT command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the MEDIA EJCT command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_media_eject_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_MEDIA_EJECT);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+
+/**
+ * @brief This method will construct the ATA read verify sector(s) command.
+ *
+ * @pre It is expected that the user has properly set the current contents
+ * of the register FIS to 0.
+ *
+ * @param[out] ata_io This parameter specifies the ATA IO request structure
+ * for which to build the ATA READ VERIFY SECTOR(S) command.
+ * @param[in] sequence This parameter specifies the translator sequence
+ * for which the command is being constructed.
+ *
+ * @return none.
+ */
+void sati_ata_read_verify_sectors_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
+
+ //According to SAT-2 (v7) 9.11.3
+ sati_set_ata_sector_count(register_fis, 1);
+
+ //According to SAT-2 (v7) 9.11.3, set LBA to a value between zero and the
+ //maximum LBA supported by the ATA device in its current configuration.
+ //From the unit test, it seems we have to set LBA to a non-zero value.
+ sati_set_ata_lba_low(register_fis, 1);
+
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct a ATA SMART Return Status command so the
+ * status of the ATA device can be returned. The status of the SMART
+ * threshold will be returned by this command.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_smart_return_status_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 feature_value
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_SMART);
+
+ sati_set_ata_features(register_fis, feature_value);
+
+ sati_set_ata_lba_high(register_fis, 0xC2);
+ sati_set_ata_lba_mid(register_fis, 0x4F);
+
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct a ATA SMART Return Status command so the
+ * status of the ATA device can be returned. The status of the SMART
+ * threshold will be returned by this command.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_smart_read_log_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 log_address,
+ U32 transfer_length
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_SMART);
+ sati_set_ata_features(register_fis, ATA_SMART_SUB_CMD_READ_LOG);
+
+ sati_set_ata_lba_high(register_fis, 0xC2);
+ sati_set_ata_lba_mid(register_fis, 0x4F);
+ sati_set_ata_lba_low(register_fis, log_address);
+
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+ sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
+ sequence->ata_transfer_length = transfer_length;
+}
+
+/**
+ * @brief This method will construct a Write Uncorrectable ATA command that
+ * will write one sector with a psuedo or flagged error. The type of
+ * error is specified by the feature value.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_write_uncorrectable_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 feature_value
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_WRITE_UNCORRECTABLE);
+ sati_set_ata_features(register_fis, feature_value);
+ sati_set_ata_sector_count(register_fis, 0x0001);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+/**
+ * @brief This method will construct a Mode Select ATA SET FEATURES command
+ * For example, Enable/Disable Write Cache, Enable/Disable Read Ahead
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_set_features_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 feature
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_SET_FEATURES);
+ sati_set_ata_features(register_fis, feature);
+ sati_ata_non_data_command(ata_io, sequence);
+}
+
+
+
+/**
+ * @brief This method will construct a Read Log ext ATA command that
+ * will request a log page based on the log_address.
+ *
+ * @param[in] log_address This parameter specifies the log page
+ * to be returned from Read Log Ext.
+ *
+ * @param[in] transfer_length This parameter specifies the size of the
+ * log page response returned by Read Log Ext.
+ *
+ * @return N/A
+ *
+ */
+void sati_ata_read_log_ext_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 log_address,
+ U32 transfer_length
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_READ_LOG_EXT);
+
+ sati_set_ata_lba_low(register_fis, log_address);
+ sati_set_ata_lba_mid(register_fis, 0x00);
+ sati_set_ata_lba_mid_exp(register_fis, 0x00);
+
+ sati_set_ata_sector_count(register_fis, 0x01);
+
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+ sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
+ sequence->ata_transfer_length = transfer_length;
+
+}
+
+/**
+* @brief This method will check if the ATA device is in the stopped power
+* state. This is used for all medium access commands for SAT
+* compliance. See SAT2r07 section 9.11.1
+*
+* @param[in] sequence - SATI sequence data with the device state.
+*
+* @return TRUE If device is stopped
+*
+*/
+BOOL sati_device_state_stopped(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+)
+{
+ if(sequence->device->state == SATI_DEVICE_STATE_STOPPED)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_NOT_READY ,
+ SCSI_ASC_INITIALIZING_COMMAND_REQUIRED,
+ SCSI_ASCQ_INITIALIZING_COMMAND_REQUIRED
+ );
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+* @brief This method will construct a ATA Read Buffer command that
+* will request PIO in data containing the target device's buffer.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+* for which to build the ATA READ VERIFY SECTOR(S) command.
+* @param[in] sequence This parameter specifies the translator sequence
+* for which the command is being constructed.
+* @return N/A
+*
+*/
+void sati_ata_read_buffer_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_READ_BUFFER);
+ sequence->data_direction = SATI_DATA_DIRECTION_IN;
+ sequence->protocol = SAT_PROTOCOL_PIO_DATA_IN;
+ sequence->ata_transfer_length = 512;
+}
+
+
+/**
+* @brief This method will construct a ATA Write Buffer command that
+* will send PIO out data to the target device's buffer.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+* for which to build the ATA READ VERIFY SECTOR(S) command.
+* @param[in] sequence This parameter specifies the translator sequence
+* for which the command is being constructed.
+* @return N/A
+*
+*/
+void sati_ata_write_buffer_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_WRITE_BUFFER);
+
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+ sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT;
+ sequence->ata_transfer_length = 512;
+}
+
+
+/**
+* @brief This method will construct a ATA Download Microcode command that
+* will send PIO out data containing new firmware for the target drive.
+*
+* @param[out] ata_io This parameter specifies the ATA IO request structure
+* for which to build the ATA READ VERIFY SECTOR(S) command.
+* @param[in] sequence This parameter specifies the translator sequence
+* for which the command is being constructed.
+* @param[in] mode This parameter specifies the download microcode sub-command
+* code.
+* @param[in] allocation_length This parameter specifies the number of bytes
+* being sent to the target device.
+* @param[in] buffer_offset This parameter specifies the buffer offset for the
+* data sent to the target device.
+*
+* @return N/A
+*
+*/
+void sati_ata_download_microcode_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 mode,
+ U32 allocation_length,
+ U32 buffer_offset
+)
+{
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ sati_set_ata_command(register_fis, ATA_DOWNLOAD_MICROCODE);
+ sati_set_ata_features(register_fis, mode);
+
+ if(mode == ATA_MICROCODE_DOWNLOAD_SAVE)
+ {
+ sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
+ sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
+ }
+ else //mode == 0x03
+ {
+ sati_set_ata_sector_count(register_fis, (U8) (allocation_length >> 9));
+ sati_set_ata_lba_low(register_fis, (U8) (allocation_length >> 17));
+ sati_set_ata_lba_high(register_fis, (U8) (buffer_offset >> 9));
+ }
+
+ if((allocation_length == 0) && (buffer_offset == 0))
+ {
+ sati_ata_non_data_command(ata_io, sequence);
+ }
+ else
+ {
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+ sequence->protocol = SAT_PROTOCOL_PIO_DATA_OUT;
+ sequence->ata_transfer_length = allocation_length;
+ }
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_util.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_util.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,393 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_UTIL_H_
+#define _SATI_UTIL_H_
+
+/**
+ * @file
+ * @brief This file contains all of the interface methods, macros, structures
+ * that provide general support for SATI. Some methods can be utilized
+ * by a user to construct ATA/ATAPI commands, copy ATA device
+ * structure data, fill in sense data, etc.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#include <dev/isci/scil/intel_sata.h>
+#include <dev/isci/scil/intel_sas.h>
+
+/**
+ * This macro allows the translator to be able to handle environments where
+ * the contents of the CDB are of a different endian nature of byte swapped
+ * in some fashion.
+ */
+#define sati_get_cdb_byte(the_cdb, index) (the_cdb)[(index)]
+
+#define sati_get_ata_status(the_reg_fis) ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->status
+#define sati_get_ata_error(the_reg_fis) ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->error
+
+#define sati_get_ata_command(the_reg_fis) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command
+
+#define sati_get_ata_sector_count(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->sector_count
+#define sati_get_ata_sector_count_exp(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->sector_count_exp
+#define sati_get_ata_lba_low(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_low
+#define sati_get_ata_lba_mid(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_mid
+#define sati_get_ata_lba_high(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_high
+#define sati_get_ata_sector_count_ext(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->sector_count_exp
+#define sati_get_ata_lba_low_ext(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_low_exp
+#define sati_get_ata_lba_mid_ext(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_mid_exp
+#define sati_get_ata_lba_high_ext(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->lba_high_exp
+#define sati_get_ata_device(the_reg_fis) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->device
+
+#define sati_set_ata_status(the_reg_fis, value) \
+ ((SATA_FIS_REG_D2H_T*)(the_reg_fis))->status = (value)
+#define sati_set_sata_fis_type(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->fis_type = (value)
+#define sati_set_sata_command_flag(the_reg_fis) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command_flag = 1
+#define sati_clear_sata_command_flag(the_reg_fis) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command_flag = 0
+
+#define sati_set_ata_command(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->command = (value)
+#define sati_set_ata_features(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->features = (value)
+#define sati_set_ata_features_exp(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->features_exp = (value)
+#define sati_set_ata_control(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->control = (value)
+#define sati_set_ata_sector_count(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->sector_count = (value)
+#define sati_set_ata_sector_count_exp(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->sector_count_exp = (value)
+#define sati_set_ata_lba_low(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_low = (value)
+#define sati_set_ata_lba_mid(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_mid = (value)
+#define sati_set_ata_lba_high(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_high = (value)
+#define sati_set_ata_lba_low_exp(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_low_exp = (value)
+#define sati_set_ata_lba_mid_exp(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_mid_exp = (value)
+#define sati_set_ata_lba_high_exp(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->lba_high_exp = (value)
+#define sati_set_ata_device_head(the_reg_fis, value) \
+ ((SATA_FIS_REG_H2D_T*)(the_reg_fis))->device = (value)
+
+#define ATA_MID_REGISTER_THRESHOLD_EXCEEDED 0xF4
+#define ATA_HIGH_REGISTER_THRESHOLD_EXCEEDED 0x2C
+
+#define ATA_MICROCODE_OFFSET_DOWNLOAD 0x03
+#define ATA_MICROCODE_DOWNLOAD_SAVE 0x07
+
+#ifndef MIN
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#endif
+
+#ifndef MAX
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+#endif
+
+
+void sati_ata_non_data_command(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_identify_device_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_execute_device_diagnostic_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_identify_device_copy_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * destination_scsi_io,
+ U32 destination_offset,
+ U8 * source_buffer,
+ U32 source_offset,
+ U32 length,
+ BOOL use_printable_chars
+);
+
+void sati_copy_data(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * destination_scsi_io,
+ U32 destination_offset,
+ U8 * source_buffer,
+ U32 length
+);
+
+void sati_ata_identify_device_get_sector_info(
+ ATA_IDENTIFY_DEVICE_DATA_T * identify,
+ U32 * lba_high,
+ U32 * lba_low,
+ U32 * sector_size
+);
+
+void sati_ata_check_power_mode_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+U8 sati_scsi_get_sense_data_length(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+);
+
+void sati_scsi_common_response_iu_construct(
+ SCI_SSP_RESPONSE_IU_T * rsp_iu,
+ U8 scsi_status,
+ U8 sense_data_length,
+ U8 data_present
+);
+
+void sati_scsi_sense_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+);
+
+void sati_scsi_fixed_sense_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 response_code,
+ U8 scsi_status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+);
+
+void sati_scsi_descriptor_sense_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 response_code,
+ U8 scsi_status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+);
+
+void sati_scsi_read_ncq_error_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_input_data,
+ U8 scsi_status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+);
+
+void sati_scsi_read_error_sense_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U8 status,
+ U8 sense_key,
+ U8 additional_sense_code,
+ U8 additional_sense_code_qualifier
+);
+
+void sati_scsi_response_data_construct(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U8 response_data
+);
+
+void sati_get_data_byte(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 byte_offset,
+ U8 * value
+);
+
+void sati_set_data_byte(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 byte_offset,
+ U8 value
+);
+
+void sati_set_data_dword(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ U32 byte_offset,
+ U32 value
+);
+
+void sati_set_sense_data_byte(
+ U8 * sense_data,
+ U32 max_sense_data_len,
+ U32 byte_offset,
+ U8 value
+);
+
+void sati_ata_flush_cache_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_standby_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U16 count
+);
+
+void sati_ata_standby_immediate_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_idle_immediate_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_idle_immediate_unload_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_idle_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_media_eject_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_read_verify_sectors_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_smart_return_status_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 feature_value
+);
+
+void sati_ata_smart_read_log_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 log_address,
+ U32 transfer_length
+);
+
+void sati_ata_write_uncorrectable_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 feature_value
+);
+
+void sati_ata_set_features_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 feature
+);
+
+void sati_ata_read_log_ext_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 log_address,
+ U32 transfer_length
+);
+
+BOOL sati_device_state_stopped(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io
+);
+
+void sati_ata_read_buffer_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_write_buffer_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence
+);
+
+void sati_ata_download_microcode_construct(
+ void * ata_io,
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ U8 mode,
+ U32 block_count,
+ U32 buffer_offset
+);
+
+#endif // _SATI_UTIL_H_
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_verify.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_verify.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,273 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations for translating
+ * the SCSI VERIFY (10, 12, 16-byte) commands.
+ */
+
+#if !defined(DISABLE_SATI_VERIFY)
+
+#include <dev/isci/scil/sati_verify.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/sati_move.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_sat.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the SCSI VERIFY command translation
+ * functionality common to all VERIFY command sizes.
+ * This includes:
+ * - setting the command register
+ * - setting the device head register
+ * - filling in fields in the SATI_TRANSLATOR_SEQUENCE object.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the method was successfully completed.
+ * @retval SATI_SUCCESS This is returned in all other cases.
+ */
+static
+SATI_STATUS sati_verify_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U8 * register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
+
+ /**
+ * The translator doesn't support performing the byte check operation.
+ * As a result, error the request if the BYTCHK bit is set.
+ */
+ if ((sati_get_cdb_byte(cdb, 1) & SCSI_VERIFY_BYTCHK_ENABLED))
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ sequence->protocol = SAT_PROTOCOL_NON_DATA;
+ sequence->data_direction = SATI_DATA_DIRECTION_NONE;
+
+ sati_set_ata_device_head(register_fis, ATA_DEV_HEAD_REG_LBA_MODE_ENABLE);
+
+ // Ensure the device supports the 48 bit feature set.
+ if (sequence->device->capabilities & SATI_DEVICE_CAP_48BIT_ENABLE)
+ sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS_EXT);
+ else
+ sati_set_ata_command(register_fis, ATA_READ_VERIFY_SECTORS);
+
+ return SATI_SUCCESS;
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs all of the translation required for a
+ * SCSI VERIFY 10 byte CDB.
+ * This includes:
+ * - logical block address translation
+ * - transfer length (sector count) translation
+ * - translation items common to all VERIFY CDB sizes.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation was successful.
+ * For more information on return values please reference
+ * sati_move_set_sector_count(), sati_verify_translate_command()
+ */
+SATI_STATUS sati_verify_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_VERIFY_10;
+
+ // Fill in the Logical Block Address fields and sector count registers.
+ sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+ status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
+ if (status != SATI_SUCCESS)
+ return status;
+
+ return sati_verify_translate_command(sequence, scsi_io, ata_io);
+ }
+}
+
+/**
+ * @brief This method performs all of the translation required for a
+ * SCSI VERIFY 12 byte CDB.
+ * This includes:
+ * - logical block address translation
+ * - transfer length (sector count) translation
+ * - translation items common to all VERIFY CDB sizes.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation was successful.
+ * For more information on return values please reference
+ * sati_move_set_sector_count(), sati_verify_translate_command()
+ */
+SATI_STATUS sati_verify_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
+ (sati_get_cdb_byte(cdb, 7) << 16) |
+ (sati_get_cdb_byte(cdb, 8) << 8) |
+ (sati_get_cdb_byte(cdb, 9));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_VERIFY_12;
+
+ // Fill in the Logical Block Address fields and sector count registers.
+ sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+ status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
+ if (status != SATI_SUCCESS)
+ return status;
+
+ return sati_verify_translate_command(sequence, scsi_io, ata_io);
+ }
+}
+
+/**
+ * @brief This method performs all of the translation required for a
+ * SCSI VERIFY 16 byte CDB.
+ * This includes:
+ * - logical block address translation
+ * - transfer length (sector count) translation
+ * - translation items common to all VERIFY CDB sizes.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation was successful.
+ * For more information on return values please reference
+ * sati_move_set_sector_count(), sati_verify_translate_command()
+ */
+SATI_STATUS sati_verify_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
+ (sati_get_cdb_byte(cdb, 11) << 16) |
+ (sati_get_cdb_byte(cdb, 12) << 8) |
+ (sati_get_cdb_byte(cdb, 13));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_VERIFY_16;
+
+ // Fill in the Logical Block Address field.
+ status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+ if (status != SATI_SUCCESS)
+ return status;
+
+ // Fill in the Sector Count fields.
+ status = sati_move_set_sector_count(sequence,scsi_io,ata_io,sector_count,0);
+ if (status != SATI_SUCCESS)
+ return status;
+
+ return sati_verify_translate_command(sequence, scsi_io, ata_io);
+ }
+}
+
+#endif // !defined(DISABLE_SATI_VERIFY)
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_verify.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_verify.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,83 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_VERIFY_H_
+#define _SATI_VERIFY_H_
+
+/**
+ * @file
+ * @brief This file contains the method prototypes and constructs
+ * for translating the SCSI VERIFY (10, 12, 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_verify_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_verify_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_verify_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_VERIFY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,321 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the method implementations required to
+ * translate the SCSI write (6, 10, 12, or 16-byte) commands.
+ */
+
+#include <dev/isci/scil/sati_move.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+//******************************************************************************
+//* P R I V A T E M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method performs the common translation functionality for
+ * all SCSI write operations that are 10 bytes in size or larger.
+ * Translated/Written items include:
+ * - Force Unit Access (FUA)
+ * - Sector Count/Transfer Length
+ * - Command register
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ * to be transferred by this request.
+ * @param[in] device_head This parameter points to device head register
+ * that is to be written into the ATA task file (register FIS).
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_set_sector_count() for additional return values.
+ */
+static
+SATI_STATUS sati_write_large_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 * device_head
+)
+{
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+
+ return sati_move_large_translate_command(
+ sequence,
+ scsi_io,
+ ata_io,
+ sector_count,
+ device_head
+ );
+}
+
+/**
+ * @brief This method performs the common translation functionality for
+ * all SCSI write operations containing a 32-bit logical block
+ * address.
+ * Translated/Written items include:
+ * - Logical Block Address (LBA)
+ * - Force Unit Access (FUA)
+ * - Sector Count/Transfer Length
+ * - Command register
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @param[in] sector_count This parameter specifies the number of sectors
+ * to be transferred by this request.
+ * @param[in] control_byte_offset This parameter specifies the byte offset
+ * into the command descriptor block at which the control byte
+ * is located.
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_move_32_bit_lba_translate_command(), sati_move_set_sector_count()
+ * for additional return values.
+ */
+static
+SATI_STATUS sati_write_32_bit_lba_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io,
+ U32 sector_count,
+ U8 control_byte_offset
+)
+{
+ U8 device_head = 0;
+ SATI_STATUS status;
+
+ status = sati_write_large_translate_command(
+ sequence, scsi_io, ata_io, sector_count, &device_head
+ );
+
+ if (status == SATI_SUCCESS)
+ {
+ status = sati_move_32_bit_lba_translate_command(
+ sequence, scsi_io, ata_io, device_head
+ );
+ }
+
+ return status;
+}
+
+//******************************************************************************
+//* P U B L I C M E T H O D S
+//******************************************************************************
+
+/**
+ * @brief This method will translate the SCSI write command into a
+ * corresponding ATA write 6 command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+ * sense data has been created as a result of something specified
+ * in the CDB.
+ */
+SATI_STATUS sati_write_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->data_direction = SATI_DATA_DIRECTION_OUT;
+ sequence->type = SATI_SEQUENCE_WRITE_6;
+
+ return sati_move_small_translate_command(sequence, scsi_io, ata_io);
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI write 10 command into a
+ * corresponding ATA write command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * It ensures that all translation required for this command is
+ * performed successfully.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_write_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_write_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_WRITE_10;
+
+ return sati_write_32_bit_lba_translate_command(
+ sequence, scsi_io, ata_io, sector_count, 9
+ );
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI write 12 command into a
+ * corresponding ATA write command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * It ensures that all translation required for this command is
+ * performed successfully.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_write_32_bit_lba_translate_command() for return values.
+ */
+SATI_STATUS sati_write_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 6) << 24) |
+ (sati_get_cdb_byte(cdb, 7) << 16) |
+ (sati_get_cdb_byte(cdb, 8) << 8) |
+ (sati_get_cdb_byte(cdb, 9));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_WRITE_12;
+
+ return sati_write_32_bit_lba_translate_command(
+ sequence, scsi_io, ata_io, sector_count, 11
+ );
+ }
+}
+
+/**
+ * @brief This method will translate the SCSI write 16 command into a
+ * corresponding ATA write command. Depending upon the capabilities
+ * supported by the target different ATA commands can be selected.
+ * It ensures that all translation required for this command is
+ * performed successfully.
+ * For more information on the parameters passed to this method,
+ * please reference sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @see sati_write_large_translate_command(), sati_move_translate_64_bit_lba()
+ * for additional return values.
+ */
+SATI_STATUS sati_write_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+ U8 device_head = 0;
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ U32 sector_count = (sati_get_cdb_byte(cdb, 10) << 24) |
+ (sati_get_cdb_byte(cdb, 11) << 16) |
+ (sati_get_cdb_byte(cdb, 12) << 8) |
+ (sati_get_cdb_byte(cdb, 13));
+
+ if(sati_device_state_stopped(sequence, scsi_io))
+ {
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sequence->type = SATI_SEQUENCE_WRITE_16;
+
+ // Translate the sector count, write command register, and check various
+ // other parts of the CDB.
+ status = sati_write_large_translate_command(
+ sequence, scsi_io, ata_io, sector_count, &device_head
+ );
+
+ // Attempt to translate the 64-bit LBA field from the SCSI request
+ // into the 48-bits of LBA in the ATA register FIS.
+ if (status == SATI_SUCCESS)
+ {
+ sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+ status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+ }
+
+ return status;
+ }
+}
+
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,91 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _SATI_WRITE_H_
+#define _SATI_WRITE_H_
+
+/**
+ * @file
+ * @brief This file contains the method declarations and type definitions
+ * required to translate the SCSI write (6, 10, 12, or 16-byte)
+ * commands.
+ */
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_write_6_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_WRITE_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_and_verify.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_and_verify.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,243 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the method implementations to translate
+* SCSI Write and Verify command based of the SAT spec.
+*/
+
+#if !defined(DISABLE_SATI_WRITE_AND_VERIFY)
+
+#include <dev/isci/scil/sati_write_and_verify.h>
+#include <dev/isci/scil/sati_write.h>
+#include <dev/isci/scil/sati_verify.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_scsi.h>
+
+/**
+* @brief This function translates a SCSI Write and Verify 10 command
+* into both ATA write and ATA read verify commands. This
+* happens by passing the SCSI IO, ATA IO, and Sequence pointers
+* to both the sati_write_10_translate_command and the
+* sati_verify_10_translate_command.
+*
+* @return Indicate if the command translation succeeded.
+* @retval SCI_SUCCESS This is returned if the command translation was
+* successful.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+* a problem with the translation of write long.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+* state for a sati_write_and_verify_10 translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+
+ if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+ {
+ status = sati_write_10_translate_command(sequence, scsi_io, ata_io);
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ sequence->is_translate_response_required = TRUE;
+ }
+ else if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ status = sati_verify_10_translate_command(sequence, scsi_io, ata_io);
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+ }
+ else
+ {
+ //SATI sequence is in the wrong state
+ return SATI_FAILURE;
+ }
+
+ sequence->type = SATI_SEQUENCE_WRITE_AND_VERIFY;
+ return status;
+}
+
+/**
+* @brief This function translates a SCSI Write and Verify 12 command
+* into both ATA write and ATA read verify commands. This
+* happens by passing the SCSI IO, ATA IO, and Sequence pointers
+* to both the sati_write_12_translate_command and the
+* sati_verify_12_translate_command.
+*
+* @return Indicate if the command translation succeeded.
+* @retval SCI_SUCCESS This is returned if the command translation was
+* successful.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+* a problem with the translation of write long.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+* state for a sati_write_and_verify_12 translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+
+ if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+ {
+ status = sati_write_12_translate_command(sequence, scsi_io, ata_io);
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ sequence->is_translate_response_required = TRUE;
+ }
+ else if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ status = sati_verify_12_translate_command(sequence, scsi_io, ata_io);
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+ }
+ else
+ {
+ //SATI sequence is in the wrong state
+ return SATI_FAILURE;
+ }
+
+ sequence->type = SATI_SEQUENCE_WRITE_AND_VERIFY;
+ return status;
+}
+
+/**
+* @brief This function translates a SCSI Write and Verify 16 command
+* into both ATA write and ATA read verify commands. This
+* happens by passing the SCSI IO, ATA IO, and Sequence pointers
+* to both the sati_write_16_translate_command and the
+* sati_verify_16_translate_command.
+*
+* @return Indicate if the command translation succeeded.
+* @retval SCI_SUCCESS This is returned if the command translation was
+* successful.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+* a problem with the translation of write long.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+* state for a sati_write_and_verify_16 translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ SATI_STATUS status;
+
+ if(sequence->state == SATI_SEQUENCE_STATE_INITIAL)
+ {
+ status = sati_write_16_translate_command(sequence, scsi_io, ata_io);
+ sequence->state = SATI_SEQUENCE_STATE_INCOMPLETE;
+ sequence->is_translate_response_required = TRUE;
+ }
+ else if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ status = sati_verify_16_translate_command(sequence, scsi_io, ata_io);
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+ }
+ else
+ {
+ //SATI sequence is in the wrong state
+ return SATI_FAILURE;
+ }
+
+ sequence->type = SATI_SEQUENCE_WRITE_AND_VERIFY;
+ return status;
+}
+
+/**
+* @brief This function is the response to a sati_write_and_verify
+ translation. Since no response translation is required
+ this function will only check the sequence state and return
+ status.
+*
+* @return Indicate if the command response translation succeeded.
+* @retval SCI_COMPLETE This is returned if the command translation
+ is successful and requires no more work.
+* @retval SATI_SEQUENCE_INCOMPLETE This is returned if the command
+ translation has finished sending the ATA Write command but
+ still needs to complete the Verify portion.
+* @retval SATI_FAILURE is returned if there the sequence is out of
+* state for a sati_write_and_verify translation.
+*
+*/
+SATI_STATUS sati_write_and_verify_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ if(sequence->state == SATI_SEQUENCE_STATE_INCOMPLETE)
+ {
+ return SATI_SEQUENCE_INCOMPLETE;
+ }
+ else if(sequence->state == SATI_SEQUENCE_STATE_AWAIT_RESPONSE)
+ {
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ return SATI_COMPLETE;
+ }
+
+ return SATI_FAILURE;
+}
+
+#endif //!defined(DISABLE_SATI_WRITE_AND_VERIFY)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_and_verify.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_and_verify.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,90 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+* @file
+* @brief This file contains the method definitions to translate
+* SCSI Write and Verify command based of the SAT spec.
+*/
+
+#ifndef _SATI_WRITE_AND_VERIFY_H_
+#define _SATI_WRITE_AND_VERIFY_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_write_and_verify_10_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_and_verify_12_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_and_verify_16_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_and_verify_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif //#ifndef _SATI_WRITE_AND_VERIFY_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_buffer.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_buffer.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,254 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+* @file
+* @brief This file contains the method implementations to translate
+* SCSI Write Buffer command based of the SAT2v07 spec.
+*/
+
+#include <dev/isci/scil/sati_write_buffer.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_util.h>
+
+#define WRITE_BUFFER_WRITE_DATA 0x02
+#define WRITE_BUFFER_DOWNLOAD_SAVE 0x05
+#define WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE 0x07
+#define BLOCK_SIZE 512
+
+/**
+* @brief This method will translate the SCSI Write Buffer command
+* into a corresponding ATA Write Buffer and Download Microcode commands.
+* For more information on the parameters passed to this method,
+* please reference sati_translate_command().
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_SUCCESS indicates that the translation was supported and occurred
+* without error.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+* there is a translation failure.
+*/
+SATI_STATUS sati_write_buffer_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ SATI_STATUS status = SATI_FAILURE;
+ U32 allocation_length;
+ U32 buffer_offset;
+
+ allocation_length = ((sati_get_cdb_byte(cdb, 6) << 16) |
+ (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8)));
+
+ buffer_offset = ((sati_get_cdb_byte(cdb, 3) << 16) |
+ (sati_get_cdb_byte(cdb, 4) << 8) |
+ (sati_get_cdb_byte(cdb, 5)));
+
+ sequence->allocation_length = allocation_length;
+
+ switch(sati_get_cdb_byte(cdb, 1))
+ {
+ case WRITE_BUFFER_WRITE_DATA:
+ if((allocation_length == BLOCK_SIZE) && (buffer_offset == 0) &&
+ (sati_get_cdb_byte(cdb, 2) == 0))
+ {
+ sati_ata_write_buffer_construct(ata_io, sequence);
+ sequence->type = SATI_SEQUENCE_WRITE_BUFFER;
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+ status = SATI_SUCCESS;
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ break;
+
+ case WRITE_BUFFER_DOWNLOAD_SAVE:
+
+ sati_ata_download_microcode_construct(
+ ata_io,
+ sequence,
+ ATA_MICROCODE_DOWNLOAD_SAVE,
+ allocation_length,
+ buffer_offset
+ );
+
+ sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE;
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+ status = SATI_SUCCESS;
+ break;
+
+ case WRITE_BUFFER_OFFSET_DOWNLOAD_SAVE:
+ if(((allocation_length & 0x000001FF) == 0) && //Bits 08:00 need to be zero per SAT2v7
+ ((buffer_offset & 0x000001FF) == 0) &&
+ (allocation_length <= sequence->device->max_blocks_per_microcode_command) &&
+ (allocation_length >= sequence->device->min_blocks_per_microcode_command))
+ {
+ sati_ata_download_microcode_construct(
+ ata_io,
+ sequence,
+ ATA_MICROCODE_OFFSET_DOWNLOAD,
+ allocation_length,
+ buffer_offset
+ );
+
+ sequence->type = SATI_SEQUENCE_WRITE_BUFFER_MICROCODE;
+ sequence->state = SATI_SEQUENCE_STATE_AWAIT_RESPONSE;
+ status = SATI_SUCCESS;
+ }
+ else
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ break;
+
+ default: //unsupported Write Buffer Mode
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+ return status;
+}
+
+/**
+* @brief This method will complete the Write Buffer Translation by checking
+* for ATA errors and then creating a unit attention condition for
+* changed microcode.
+*
+* @return Indicates if the command translation succeeded.
+* @retval SATI_FAILURE_CHECK_RESPONSE_DATA This value is returned if
+* there is a translation failure.
+* @retval SATI_COMPLETE indicates that the translation was supported, occurred without
+* error, and no additional translation is necessary.
+*/
+SATI_STATUS sati_write_buffer_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+ U8 ata_status = (U8) sati_get_ata_status(register_fis);
+ SATI_STATUS status = SATI_FAILURE;
+
+ if (ata_status & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_NO_ADDITIONAL_SENSE,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ status = SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ switch(sequence->type)
+ {
+ case SATI_SEQUENCE_WRITE_BUFFER_MICROCODE:
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_GOOD,
+ SCSI_SENSE_UNIT_ATTENTION,
+ SCSI_ASC_MICROCODE_HAS_CHANGED,
+ SCSI_ASCQ_MICROCODE_HAS_CHANGED
+ );
+ status = SATI_COMPLETE;
+ break;
+
+ default:
+ status = SATI_COMPLETE;
+ break;
+ }
+ }
+
+ sequence->state = SATI_SEQUENCE_STATE_FINAL;
+ return status;
+}
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_buffer.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_buffer.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,78 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* BSD LICENSE
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+* @file
+* @brief This file contains the method definitions to translate
+* SCSI Write Buffer command based of the SAT2v07 spec.
+*/
+
+#ifndef _SATI_WRITE_BUFFER_H_
+#define _SATI_WRITE_BUFFER_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+SATI_STATUS sati_write_buffer_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_buffer_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_WRITE_BUFFER_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_long.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_long.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,259 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ * @brief This file contains the implementation to translate
+ * SCSI Write Long 10 and 16 commands based on the SAT spec.
+ */
+
+#if !defined(DISABLE_SATI_WRITE_LONG)
+
+#include <dev/isci/scil/sati_write_long.h>
+#include <dev/isci/scil/sati_device.h>
+#include <dev/isci/scil/sati_util.h>
+#include <dev/isci/scil/intel_scsi.h>
+#include <dev/isci/scil/intel_ata.h>
+#include <dev/isci/scil/intel_sat.h>
+#include <dev/isci/scil/sati_callbacks.h>
+#include <dev/isci/scil/sati_move.h>
+
+#define LOGICAL_PER_PHYSICAL_SECTOR 0xF
+
+#define WR_UNCOR_BIT 0x02
+#define WR_UNCOR_PBLOCK_BIT 0x03
+#define COR_DIS_WR_UNCORR_BIT 0x06
+
+
+/**
+ * @brief This method will translate the write long 10 & 16 SCSI commands into
+ * ATA write uncorrectable commands. For more information on the
+ * parameters passed to this method, please reference
+ * sati_translate_command().
+ *
+ * @return Indicate if the command translation succeeded.
+ * @retval SCI_SUCCESS This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+ * a problem with the translation of write long.
+ *
+ */
+SATI_STATUS sati_write_long_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * cdb = sati_cb_get_cdb_address(scsi_io);
+ SATI_STATUS status = SATI_FAILURE;
+ U16 byte_transfer_length;
+ U8 device_head = 0;
+
+ if((sequence->device->capabilities &
+ SATI_DEVICE_CAP_WRITE_UNCORRECTABLE_ENABLE) == 0)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_COMMAND_OPERATION_CODE,
+ SCSI_ASCQ_INVALID_COMMAND_OPERATION_CODE
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ //Write Long 10
+ if(sati_get_cdb_byte(cdb, 0) == SCSI_WRITE_LONG_10)
+ {
+ byte_transfer_length = (sati_get_cdb_byte(cdb, 7) << 8) |
+ (sati_get_cdb_byte(cdb, 8));
+
+ sati_move_translate_32_bit_lba(sequence, scsi_io, ata_io);
+ }
+ else //Write Long 16
+ {
+ byte_transfer_length = (sati_get_cdb_byte(cdb, 12) << 8) |
+ (sati_get_cdb_byte(cdb, 13));
+
+ status = sati_move_translate_64_bit_lba(sequence, scsi_io, ata_io);
+
+ if( status == SATI_FAILURE_CHECK_RESPONSE_DATA)
+ {
+ return status;
+ }
+ }
+
+
+ sati_move_translate_command(sequence, scsi_io, ata_io, device_head);
+
+ if( byte_transfer_length != 0 )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+
+ switch(SATI_WRITE_LONG_GET_COR_WR_PB_BITS(cdb))
+ {
+ case WR_UNCOR_BIT :
+
+ if( (sequence->device->capabilities &
+ SATI_DEVICE_CAP_MULTIPLE_SECTORS_PER_PHYSCIAL_SECTOR) != 0 )
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ sati_ata_write_uncorrectable_construct(
+ ata_io,
+ sequence,
+ ATA_WRITE_UNCORRECTABLE_PSUEDO
+ );
+ sequence->type = SATI_SEQUENCE_WRITE_LONG;
+ status = SATI_SUCCESS;
+ }
+ break;
+
+ case WR_UNCOR_PBLOCK_BIT :
+
+ sati_ata_write_uncorrectable_construct(
+ ata_io,
+ sequence,
+ ATA_WRITE_UNCORRECTABLE_PSUEDO
+ );
+ sequence->type = SATI_SEQUENCE_WRITE_LONG;
+ status = SATI_SUCCESS;
+ break;
+
+ case COR_DIS_WR_UNCORR_BIT :
+
+ sati_ata_write_uncorrectable_construct(
+ ata_io,
+ sequence,
+ ATA_WRITE_UNCORRECTABLE_FLAGGED
+ );
+ sequence->type = SATI_SEQUENCE_WRITE_LONG;
+ status = SATI_SUCCESS;
+ break;
+
+ default :
+
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ILLEGAL_REQUEST,
+ SCSI_ASC_INVALID_FIELD_IN_CDB,
+ SCSI_ASCQ_INVALID_FIELD_IN_CDB
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ break;
+ }
+ return status;
+}
+
+/**
+ * @brief This method will translate the response to the SATI Write Long
+ * translation. This response is only error checking the
+ * ATA Write Uncorrectable command.
+ *
+ * @return SATI_STATUS Indicates if the response translation succeeded.
+ * @retval SCI_COMPLETE This is returned if the command translation was
+ * successful.
+ * @retval SATI_FAILURE_CHECK_RESPONSE_DATA is returned if there was
+ * a problem with the translation of write long.
+ */
+SATI_STATUS sati_write_long_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+)
+{
+ U8 * register_fis = sati_cb_get_d2h_register_fis_address(ata_io);
+
+ if (sati_get_ata_status(register_fis) & ATA_STATUS_REG_ERROR_BIT)
+ {
+ sati_scsi_sense_data_construct(
+ sequence,
+ scsi_io,
+ SCSI_STATUS_CHECK_CONDITION,
+ SCSI_SENSE_ABORTED_COMMAND,
+ SCSI_ASC_COMMAND_SEQUENCE_ERROR,
+ SCSI_ASCQ_NO_ADDITIONAL_SENSE
+ );
+ return SATI_FAILURE_CHECK_RESPONSE_DATA;
+ }
+ else
+ {
+ return SATI_COMPLETE;
+ }
+}
+
+#endif // !defined(DISABLE_SATI_WRITE_LONG)
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sati_write_long.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sati_write_long.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,83 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ * @brief This file contains the method definitions to translate
+ * SCSI Write Long command based of the SAT spec.
+ */
+
+#ifndef _SATI_WRITE_LONG_H_
+#define _SATI_WRITE_LONG_H_
+
+#include <dev/isci/scil/sati_types.h>
+#include <dev/isci/scil/sati_translator_sequence.h>
+
+#define SATI_WRITE_LONG_GET_COR_WR_PB_BITS(cdb) \
+ (( sati_get_cdb_byte(cdb, 1) & 0xE0) \
+ >> 5)
+
+
+SATI_STATUS sati_write_long_translate_command(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+SATI_STATUS sati_write_long_translate_response(
+ SATI_TRANSLATOR_SEQUENCE_T * sequence,
+ void * scsi_io,
+ void * ata_io
+);
+
+#endif // _SATI_WRITE_LONG_H_
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sci_abstract_list.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sci_abstract_list.c Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,599 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/**
+ * @file
+ *
+ * @brief This file contains the implementation of an abstract list class.
+ * This class will allow for the same item to occur multiple times in
+ * the list. It will provide an interface that is similar to the
+ * C++ standard template list interface.
+ */
+
+//******************************************************************************
+//*
+//* I N C L U D E S
+//*
+//******************************************************************************
+
+#include <dev/isci/scil/sci_abstract_list.h>
+
+
+//******************************************************************************
+//*
+//* P R I V A T E M E M B E R S
+//*
+//******************************************************************************
+
+//******************************************************************************
+//*
+//* P R O T E C T E D M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * @brief Initialize the abstract list
+ *
+ * @pre The supplied free pool should be constructed prior to utilization
+ * of this abstract list. It isn't mandatory for the free pool to be
+ * constructed before invoking this method, but suggested.
+ *
+ * @param[in] list This parameter specifies the abstract list to be
+ * constructed.
+ * @param[in] free_pool This parameter specifies the free pool to be
+ * utilized as the repository of free elements for list usage.
+ *
+ * @return none
+ */
+void sci_abstract_list_construct(
+ SCI_ABSTRACT_LIST_T * list,
+ SCI_ABSTRACT_ELEMENT_POOL_T * free_pool
+)
+{
+ memset(list, 0, sizeof(SCI_ABSTRACT_LIST_T));
+ list->free_pool = free_pool;
+}
+
+/**
+ * Initialize the abstract list with its free pool
+ *
+ * @param[in] pool
+ * the free pool from which the elements will be extracted
+ * @param[in] list_elements
+ * the array of list elements to be added to the free list
+ * @param[in] element_count
+ * the count of the elements to be added to the free list these should be
+ * the same as the array size of list elements
+ *
+ * @return none
+ */
+void sci_abstract_element_pool_construct(
+ SCI_ABSTRACT_ELEMENT_POOL_T * pool,
+ SCI_ABSTRACT_ELEMENT_T * list_elements,
+ int element_count
+)
+{
+ int index;
+
+ memset(pool, 0, sizeof(SCI_ABSTRACT_ELEMENT_POOL_T));
+ memset(list_elements, 0, sizeof(SCI_ABSTRACT_ELEMENT_T) * element_count);
+
+ pool->elements = list_elements;
+ pool->max_elements = element_count;
+
+ // Loop through all of the elements in the array and push them onto the
+ // pool's free list.
+ for (index = element_count - 1; index >= 0; index--)
+ {
+ private_pool_free(pool, &(list_elements[index]));
+ }
+}
+
+
+#ifdef USE_ABSTRACT_LIST_FUNCTIONS
+
+//******************************************************************************
+//*
+//* P U B L I C M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * Simply return the front element pointer of the list. This returns an element
+ * element as opposed to what the element is pointing to.
+ */
+SCI_ABSTRACT_ELEMENT_T * sci_abstract_list_get_front(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ return (list_p)->elements.front_p;
+}
+
+/**
+ * This method simply returns the object pointed to by the head (front) of
+ * the list.
+ */
+void * sci_abstract_list_front(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ return
+ ( ( (list_p)->elements.front_p ) ? ((list_p)->elements.front_p->object_p) : NULL );
+}
+
+/**
+ * This method simply returns the object pointed to by the tail (back) of
+ * the list.
+ */
+void * sci_abstract_list_back(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ return
+ ( ( (list_p)->elements.back_p ) ? ((list_p)->elements.back_p->object_p) : NULL );
+}
+
+/**
+ * This method will return FALSE if the list is not empty.
+ */
+BOOL sci_abstract_list_is_empty(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ return ( (list_p)->elements.front_p == NULL );
+}
+
+
+/**
+ * This method will return the number of elements queued in the list.
+ */
+U32 sci_abstract_list_size(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ return ( (list_p)->elements.size );
+}
+
+
+/**
+ * This method simply returns the next list element in the list.
+ */
+SCI_ABSTRACT_ELEMENT_T * sci_abstract_list_get_next(
+ SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+ return ( (alElement_p)->next_p );
+}
+
+
+#if defined(SCI_LOGGING)
+/**
+ * This method simply prints the contents of the list.
+ */
+void sci_abstract_list_print(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_T * alElement_p = list_p->elements.front_p;
+
+ while (alElement_p != NULL)
+ {
+#ifdef UNIT_TEST_DEBUG
+ /* Check to see if we found the object for which we are searching. */
+ printf("ITEM next_p 0x%x prev_p 0x%x obj_p 0x%x, 0x%x\n",
+ alElement_p->next_p,
+ alElement_p->previous_p,
+ (U32*) (alElement_p->object_p));
+#endif
+ alElement_p = alElement_p->next_p;
+ }
+}
+#endif // defined(SCI_LOGGING)
+
+
+/**
+ * This method will simply search the supplied list for the desired object.
+ * It will return a pointer to the object, if it is found. Otherwise
+ * it will return NULL.
+ */
+void * sci_abstract_list_find(
+ SCI_ABSTRACT_LIST_T * list_p,
+ void * obj_p
+)
+{
+ return
+ sci_abstract_list_get_object(private_find(&(list_p)->elements, (obj_p)));
+}
+
+
+/**
+ * This method will simply remove the element at the back (tail) of the list.
+ * It will return a pointer to the object that was removed or NULL if not
+ * found.
+ */
+void * sci_abstract_list_popback(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+ SCI_ABSTRACT_ELEMENT_T * alElement_p = elem_list->back_p;
+ void * obj_p = NULL;
+
+ if (alElement_p != NULL)
+ {
+ obj_p = alElement_p->object_p;
+ if (elem_list->back_p == elem_list->front_p)
+ {
+ elem_list->back_p = elem_list->front_p = NULL;
+ }
+ else
+ {
+ elem_list->back_p = elem_list->back_p->previous_p;
+ elem_list->back_p->next_p = NULL;
+ }
+
+ elem_list->size--;
+ private_pool_free((list_p)->free_pool, alElement_p);
+ }
+
+ return obj_p;
+}
+
+/**
+ * This method simply removes the list element at the head of the list
+ * and returns the pointer to the object that was removed.
+ */
+void * sci_abstract_list_popfront(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_T * alElement_p =
+ private_pop_front(&(list_p)->elements);
+ void * obj_p = NULL;
+
+ if (alElement_p != NULL)
+ {
+ obj_p = alElement_p->object_p;
+ private_pool_free((list_p)->free_pool, alElement_p);
+ }
+
+ return obj_p;
+}
+
+
+
+/**
+ * This method will erase (remove) all instances of the supplied object from
+ * anywhere in the list.
+ */
+void sci_abstract_list_erase(
+ SCI_ABSTRACT_LIST_T * list_p,
+ void * obj_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+ SCI_ABSTRACT_ELEMENT_T * alElement_p;
+
+ while ((alElement_p = private_find(elem_list, (obj_p))) != NULL)
+ {
+ if (alElement_p == elem_list->front_p)
+ {
+ sci_abstract_list_popfront(list_p);
+ }
+ else if (alElement_p == elem_list->back_p)
+ {
+ sci_abstract_list_popback(list_p);
+ }
+ else
+ {
+ alElement_p->previous_p->next_p = alElement_p->next_p;
+ alElement_p->next_p->previous_p = alElement_p->previous_p;
+ elem_list->size--;
+ private_pool_free((list_p)->free_pool, alElement_p);
+ }
+ }
+ return;
+}
+
+/**
+ * This method simply adds a LIST_ELEMENT for the supplied object to the back
+ * (tail) of the supplied list.
+ */
+void sci_abstract_list_pushback(
+ SCI_ABSTRACT_LIST_T * list_p,
+ void * obj_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+ SCI_ABSTRACT_ELEMENT_T * alElement_p
+ = private_pool_allocate((list_p)->free_pool);
+// assert(alElement_p != NULL);
+
+ alElement_p->object_p = (obj_p);
+
+ if (elem_list->front_p == NULL)
+ {
+ elem_list->front_p = elem_list->back_p = alElement_p;
+ }
+ else
+ {
+ elem_list->back_p->next_p = alElement_p;
+ alElement_p->previous_p = elem_list->back_p;
+ elem_list->back_p = alElement_p;
+ }
+
+ elem_list->size++;
+}
+
+
+
+/**
+ * This method simply adds a LIST_ELEMENT for the supplied object to the front
+ * (head) of the supplied list.
+ */
+void sci_abstract_list_pushfront(
+ SCI_ABSTRACT_LIST_T * list_p,
+ void * obj_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_T * alElement_p =
+ private_pool_allocate((list_p)->free_pool);
+ alElement_p->object_p = (obj_p);
+ private_push_front(&(list_p)->elements, alElement_p);
+}
+
+
+/**
+ * This method will add the objToAdd_p object to the list before the obj_p.
+ *
+ */
+void sci_abstract_list_insert(
+ SCI_ABSTRACT_LIST_T * list_p,
+ void * obj_p,
+ void * objToAdd_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_LIST_T * elem_list = &(list_p)->elements;
+
+ SCI_ABSTRACT_ELEMENT_T * obj_element = private_find(elem_list, obj_p);
+
+ SCI_ABSTRACT_ELEMENT_T * objToAdd_element =
+ private_pool_allocate((list_p)->free_pool);
+
+ objToAdd_element->object_p = objToAdd_p;
+
+ ASSERT(obj_element != NULL);
+ ASSERT(objToAdd_element != NULL);
+
+ if (obj_element == elem_list->front_p)
+ {
+ objToAdd_element->object_p = (objToAdd_p);
+ private_push_front(&(list_p)->elements, objToAdd_element);
+ }
+ else
+ {
+ obj_element->previous_p->next_p = objToAdd_element;
+ objToAdd_element->previous_p = obj_element->previous_p;
+
+ obj_element->previous_p = objToAdd_element;
+ objToAdd_element->next_p = obj_element;
+
+ elem_list->size++;
+ }
+}
+
+/**
+ * This method simply frees all the items from the list.
+ */
+void sci_abstract_list_clear(
+ SCI_ABSTRACT_LIST_T * list_p
+)
+{
+ while ((list_p)->elements.size > 0)
+ sci_abstract_list_popfront((list_p));
+}
+
+/**
+ * This method simply returns the object being pointed to by the list element
+ * (The item being listed).
+ */
+void * sci_abstract_list_get_object(
+ SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+ void * obj_p = NULL;
+ if ((alElement_p) != NULL)
+ obj_p = (alElement_p)->object_p;
+
+ return obj_p;
+}
+
+
+/**
+ * This method is simply a wrapper to provide the number of elements in
+ * the free list.
+ */
+U32 sci_abstract_list_freeList_size(
+ SCI_ABSTRACT_LIST_T * freeList
+)
+{
+ return (sci_abstract_list_size(freeList));
+}
+
+//******************************************************************************
+//*
+//* P R I V A T E M E T H O D S
+//*
+//******************************************************************************
+
+/**
+ * This method simply performs the common portion of pushing a list element
+ * onto a list.
+ *
+ * WARNING: This is a private helper method that should not be called directly
+ * by any users.
+ */
+void private_push_front(
+ SCI_ABSTRACT_ELEMENT_LIST_T * privateList_p,
+ SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+ if ((privateList_p)->front_p == NULL)
+ {
+ (privateList_p)->front_p = (privateList_p)->back_p = (alElement_p);
+ (alElement_p)->next_p = (alElement_p)->previous_p = NULL;
+ }
+ else
+ {
+ (alElement_p)->next_p = (privateList_p)->front_p;
+ (alElement_p)->previous_p = NULL;
+ (privateList_p)->front_p->previous_p = (alElement_p);
+ (privateList_p)->front_p = (alElement_p);
+ }
+
+ (privateList_p)->size++;
+}
+
+/**
+ * This method simply performs the common portion of popping a list element
+ * from a list.
+ *
+ * WARNING: This is a private helper method that should not be called directly
+ * by any users.
+ */
+SCI_ABSTRACT_ELEMENT_T * private_pop_front(
+ SCI_ABSTRACT_ELEMENT_LIST_T * privateList_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_T * alElement_p = (privateList_p)->front_p;
+
+ if (alElement_p != NULL)
+ {
+ if ((privateList_p)->front_p == (privateList_p)->back_p)
+ {
+ (privateList_p)->front_p = (privateList_p)->back_p = NULL;
+ }
+ else
+ {
+ (privateList_p)->front_p = (privateList_p)->front_p->next_p;
+ (privateList_p)->front_p->previous_p = NULL;
+ }
+
+ (privateList_p)->size--;
+ }
+
+ return alElement_p;
+}
+
+/**
+ * This method will simply search the supplied list for the desired object.
+ * It will return a pointer to the abstract_list_element if found, otherwise
+ * it will return NULL.
+ */
+SCI_ABSTRACT_ELEMENT_T * private_find(
+ SCI_ABSTRACT_ELEMENT_LIST_T * list_p,
+ void * obj_p
+)
+{
+ SCI_ABSTRACT_ELEMENT_T * alElement_p = (list_p)->front_p;
+
+ while (alElement_p != NULL)
+ {
+ /* Check to see if we found the object for which we are searching. */
+ if (alElement_p->object_p == (void*) (obj_p))
+ {
+ break;
+ }
+
+ alElement_p = alElement_p->next_p;
+ }
+
+ return alElement_p;
+}
+
+/**
+ * This private method will free the supplied list element back to the pool
+ * of free list elements.
+ */
+void private_pool_free(
+ SCI_ABSTRACT_ELEMENT_POOL_T * free_pool,
+ SCI_ABSTRACT_ELEMENT_T * alElement_p
+)
+{
+ /* Push the list element back to the head to get better locality of */
+ /* reference with the cache. */
+ private_push_front(&(free_pool)->free_list, (alElement_p));
+}
+
+/**
+ * This private method will allocate a list element from the pool of free
+ * list elements.
+ */
+SCI_ABSTRACT_ELEMENT_T * private_pool_allocate(
+ SCI_ABSTRACT_ELEMENT_POOL_T * free_pool
+)
+{
+ SCI_ABSTRACT_ELEMENT_T * alElement_p;
+
+ alElement_p = private_pop_front(&(free_pool)->free_list);
+
+ alElement_p->next_p = NULL;
+ alElement_p->previous_p = NULL;
+ alElement_p->object_p = NULL;
+
+ return alElement_p;
+}
+
+#endif // USE_ABSTRACT_LIST_FUNCTIONS
diff -r 7c1ab5fac5ed -r f370dd4be562 head/sys/dev/isci/scil/sci_abstract_list.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/isci/scil/sci_abstract_list.h Wed Feb 01 11:27:03 2012 +0200
@@ -0,0 +1,871 @@
+/*-
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/**
+ * @file
+ *
+ * @brief This file contains the interface to the abstract list class.
+ * This class will allow for the same item to occur multiple times in
+ * a list or multiple lists. It will provide an interface that is
+ * similar to the C++ standard template list interface.
+ * Methods Provided:
+ * - sci_abstract_list_front()
+ * - sci_abstract_list_back()
+ * - sci_abstract_list_is_empty()
+ * - sci_abstract_list_size()
+ * - sci_abstract_list_print()
+ * - sci_abstract_list_find()
+ * - sci_abstract_list_popback()
+ * - sci_abstract_list_popfront()
+ * - sci_abstract_list_erase()
+ * - sci_abstract_list_pushback()
+ * - sci_abstract_list_pushfront()
+ * - sci_abstract_list_get_object()
+ * - sci_abstract_list_get_next()
+ * - sci_abstract_list_insert() UNIMPLEMENTED
+ * - sci_abstract_list_clear()
+ */
+
+#ifndef _SCI_ABSTRACT_LIST_H_
+#define _SCI_ABSTRACT_LIST_H_
+
+//******************************************************************************
+//*
+//* I N C L U D E S
+//*
+//******************************************************************************
+
+#include <dev/isci/scil/sci_types.h>
+
+//******************************************************************************
+//*
+//* C O N S T A N T S
+//*
+//*******