dect
/
linux-2.6
Archived
13
0
Fork 0

isci: Intel(R) C600 Series Chipset Storage Control Unit Driver

Support for the up to 2x4-port 6Gb/s SAS controllers embedded in the
chipset.

This is a snapshot of the first publicly available version of the driver,
commit 4c1db2d0 in the 'historical' branch.

   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git historical

Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Edmund Nadolski <edmund.nadolski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams 2011-07-02 22:56:22 -07:00
parent 59c5f46fbe
commit 6f231dda68
104 changed files with 51230 additions and 0 deletions

View File

@ -830,6 +830,40 @@ config SCSI_GDTH
To compile this driver as a module, choose M here: the
module will be called gdth.
config SCSI_ISCI
tristate "Intel(R) C600 Series Chipset SAS Controller"
depends on PCI && SCSI
# little endian host assumptions
depends on X86
# (temporary): dma api misuse
depends on !DMAR
# (temporary): known alpha quality driver
depends on EXPERIMENTAL
select SCSI_SAS_LIBSAS
---help---
This driver supports the 6Gb/s SAS capabilities of the storage
control unit found in the Intel(R) C600 series chipset.
The experimental tag will be removed after the driver exits alpha
choice
prompt "Default Silicon Revision"
depends on SCSI_ISCI
default PBG_HBA_A2
# temporary A-step silicon is pre-production
config PBG_HBA_BETA
bool "B0"
config PBG_HBA_A2
bool "A2"
config PBG_HBA_A0
bool "A0"
endchoice
config SCSI_GENERIC_NCR5380
tristate "Generic NCR5380/53c400 SCSI PIO support"
depends on ISA && SCSI

View File

@ -73,6 +73,7 @@ obj-$(CONFIG_SCSI_AACRAID) += aacraid/
obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o
obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/
obj-$(CONFIG_SCSI_PM8001) += pm8001/
obj-$(CONFIG_SCSI_ISCI) += isci/
obj-$(CONFIG_SCSI_IPS) += ips.o
obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o
obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o

View File

@ -0,0 +1,30 @@
#TODO kill SCIC_SDS_4_ENABLED it is always true for this
#generation of silicon
EXTRA_CFLAGS += -DSCIC_SDS_4_ENABLED
#temporary until atapi support ready
EXTRA_CFLAGS += -DDISABLE_ATAPI
EXTRA_CFLAGS += -Idrivers/scsi/isci/core/ -Idrivers/scsi/isci/
obj-$(CONFIG_SCSI_ISCI) += isci.o
isci-objs := init.o phy.o request.o sata.o \
remote_device.o port.o timers.o deprecated.o \
host.o task.o events.o \
core/scic_sds_controller.o \
core/scic_sds_remote_device.o \
core/scic_sds_request.o \
core/scic_sds_stp_request.o \
core/scic_sds_stp_packet_request.o \
core/scic_sds_stp_remote_device.o \
core/scic_sds_port.o \
core/scic_sds_port_configuration_agent.o \
core/scic_sds_phy.o \
core/scic_sds_ssp_request.o \
core/scic_sds_remote_node_context.o \
core/scic_sds_smp_request.o \
core/scic_sds_smp_remote_device.o \
core/scic_sds_remote_node_table.o \
core/scic_sds_unsolicited_frame_control.o \
core/sci_base_memory_descriptor_list.o \
core/sci_base_state_machine.o \
core/sci_util.o

View File

@ -0,0 +1,554 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* 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 <linux/types.h>
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
* struct ATA_IDENTIFY_DEVICE - This structure depicts the ATA IDENTIFY DEVICE
* data format.
*
*
*/
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 reserved1[2]; /* words 69-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 reserved3; /* 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 reserved_for_compact_flash3[7]; /* words 169-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[37]; /* words 218-254 */
u16 integrity_word; /* word 255 */
};
#define ATA_IDENTIFY_DEVICE_GET_OFFSET(field_name) \
((unsigned long)&(((struct ata_identify_device_data *)0)->field_name))
#define ATA_IDENTIFY_DEVICE_WCE_ENABLE 0x20
#define ATA_IDENTIFY_DEVICE_RA_ENABLE 0x40
/**
* struct ATAPI_IDENTIFY_PACKET_DATA - The following structure depicts the
* ATA-ATAPI 7 version of the IDENTIFY PACKET DEVICE data structure.
*
*
*/
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 */
};
/**
* struct ata_extended_smart_self_test_log - The following structure depicts
* the ATA-8 version of the Extended SMART self test log page descriptor
* entry.
*
*
*/
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];
};
/**
* struct ata_extended_smart_self_test_log - The following structure depicts
* the ATA-8 version of the SMART self test log page descriptor entry.
*
*
*/
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];
};
/**
* struct ata_extended_smart_self_test_log - The following structure depicts
* the ATA-8 version of the Extended SMART self test log page.
*
*
*/
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 */
union ata_descriptor_entry 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 */
};
/**
* struct ata_extended_smart_self_test_log - The following structure depicts
* the ATA-8 version of the SMART self test log page.
*
*
*/
struct ata_smart_self_test_log {
u8 self_test_log_data_structure_revision_number[2]; /* bytes 0-1 */
union ata_smart_descriptor_entry 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 */
};
#endif /* _ATA_H_ */

View File

@ -0,0 +1,948 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _INTEL_SAS_H_
#define _INTEL_SAS_H_
/**
* This file contains all of the definitions relating to structures, constants,
* etc. defined by the SAS specification.
*
*
*/
#include "intel_sata.h"
#include "intel_scsi.h"
/**
* struct sci_sas_address - This structure depicts how a SAS address is
* represented by SCI.
*
*
*/
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;
};
/**
* struct sci_sas_identify_address_frame_protocols - This structure depicts the
* contents of bytes 2 and 3 in the SAS IDENTIFY ADDRESS FRAME (IAF).
*
* For specific information on each of these individual fields please reference
* the SAS specification Link layer section on address frames.
*/
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;
};
/**
* struct sci_sas_identify_address_frame - This structure depicts the contents
* of the SAS IDENTIFY ADDRESS FRAME (IAF).
*
* For specific information on each of these individual fields please reference
* the SAS specification Link layer section on address frames.
*/
struct sci_sas_identify_address_frame {
u16 address_frame_type:4;
u16 device_type:3;
u16 reserved1:1;
u16 reason:4;
u16 reserved2:4;
struct sci_sas_identify_address_frame_protocols protocols;
struct sci_sas_address device_name;
struct sci_sas_address 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];
};
/**
* struct sas_capabilities - 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.
*
*
*/
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;
};
/**
* enum _SCI_SAS_LINK_RATE - This enumeration depicts the SAS specification
* defined link speeds.
*
*
*/
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
};
/**
* enum _SCI_SAS_TASK_ATTRIBUTE - This enumeration depicts the SAM/SAS
* specification defined task attribute values for a command information
* unit.
*
*
*/
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,
};
/**
* enum _SCI_SAS_TASK_MGMT_FUNCTION - This enumeration depicts the SAM/SAS
* specification defined task management functions.
*
* This HARD_RESET function listed here is not actually defined as a task
* management function in the industry standard.
*/
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
};
/**
* enum _SCI_SAS_FRAME_TYPE - This enumeration depicts the SAS specification
* defined SSP frame types.
*
*
*/
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
};
/**
* struct sci_ssp_command_iu - 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.
*
*
*/
struct sci_ssp_command_iu {
u32 lun_upper;
u32 lun_lower;
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];
};
/**
* struct sci_ssp_task_iu - 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.
*
*
*/
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];
};
#define SSP_RESPONSE_IU_MAX_DATA 64
#define SCI_SSP_RESPONSE_IU_DATA_PRESENT_MASK (0x03)
#define sci_ssp_get_sense_data_length(sense_data_length_buffer) \
SCIC_BUILD_DWORD(sense_data_length_buffer)
#define sci_ssp_get_response_data_length(response_data_length_buffer) \
SCIC_BUILD_DWORD(response_data_length_buffer)
/**
* struct sci_ssp_response_iu - 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.
*
*
*/
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];
};
/**
* enum _SCI_SAS_DATA_PRESENT_TYPE - This enumeration depicts the SAS
* specification defined SSP data present types in struct sci_ssp_response_iu.
*
*
*/
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
};
/**
* struct sci_ssp_frame_header - 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.
*
*
*/
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;
};
/**
* struct smp_request_header - This structure defines the contents of an SMP
* Request header.
*
* For specific information on each of these individual fields please reference
* the SAS specification.
*/
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 */
};
/**
* struct smp_response_header - 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.
*
*
*/
struct smp_response_header {
u8 smp_frame_type; /* byte 0 */
u8 function; /* byte 1 */
u8 function_result; /* byte 2 */
u8 response_length; /* byte 3 */
};
/**
* struct smp_request_general - This structure defines the contents of an SMP
* Request that is comprised of the struct smp_request_header and a CRC.
*
* For specific information on each of these individual fields please reference
* the SAS specification.
*/
struct smp_request_general {
u32 crc; /* bytes 4-7 */
};
/**
* struct smp_request_phy_identifier - This structure defines the contents of
* an SMP Request that is comprised of the struct smp_request_header and a phy
* identifier. Examples: SMP_REQUEST_DISCOVER, SMP_REQUEST_REPORT_PHY_SATA.
*
* For specific information on each of these individual fields please reference
* the SAS specification.
*/
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 */
};
/**
* struct smp_request_configure_route_information - This structure defines the
* contents of an SMP Configure Route Information request.
*
* For specific information on each of these individual fields please reference
* the SAS specification.
*/
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 */
};
/**
* struct smp_request_phy_control - This structure defines the contents of an
* SMP Phy Controler request.
*
* For specific information on each of these individual fields please reference
* the SAS specification.
*/
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 */
};
/**
* struct smp_request_vendor_specific - This structure depicts the vendor
* specific space for SMP request.
*
*
*/
#define SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH 1016
struct smp_request_vendor_specific {
u8 request_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
};
/**
* struct smp_request - This structure simply unionizes the existing request
* structures into a common request type.
*
*
*/
struct smp_request {
struct smp_request_header header;
union { /* bytes 4-N */
struct smp_request_general report_general;
struct smp_request_phy_identifier discover;
struct smp_request_general report_manufacturer_information;
struct smp_request_phy_identifier report_phy_sata;
struct smp_request_phy_control phy_control;
struct smp_request_phy_identifier report_phy_error_log;
struct smp_request_phy_identifier report_route_information;
struct smp_request_configure_route_information configure_route_information;
struct smp_request_vendor_specific vendor_specific_request;
} request;
};
/**
* struct smp_response_report_general - This structure depicts the SMP Report
* General for expander devices. It adheres to the SAS-2.1 specification.
*
* For specific information on each of these individual fields please reference
* the SAS specification Application layer section on SMP.
*/
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;
};
struct smp_response_report_general_long {
struct smp_response_report_general 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;
struct sci_sas_address 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;
};
/**
* struct smp_response_report_manufacturer_information - This structure depicts
* the SMP report manufacturer information for expander devices. It adheres
* to the SAS-2.1 specification.
*
* For specific information on each of these individual fields please reference
* the SAS specification Application layer section on SMP.
*/
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];
};
#define SMP_RESPONSE_DISCOVER_FORMAT_1_1_SIZE 52
#define SMP_RESPONSE_DISCOVER_FORMAT_2_SIZE 116
/**
* struct smp_discover_response_protocols - This structure depicts the discover
* response where the supported protocols by the remote phy are specified.
*
* For specific information on each of these individual fields please reference
* the SAS specification Link layer section on address frames.
*/
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;
};
/**
* struct SMP_RESPONSE_DISCOVER_FORMAT - 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.
*
*
*/
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;
struct smp_discover_response_protocols protocols;
struct sci_sas_address sas_address;
struct sci_sas_address 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 {
struct sci_sas_address 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;
struct sci_sas_address 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;
};
/**
* struct smp_response_report_phy_sata - 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.
*
*
*/
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];
};
struct smp_response_vendor_specific {
u8 response_bytes[SMP_REQUEST_VENDOR_SPECIFIC_MAX_LENGTH];
};
union smp_response_body {
struct smp_response_report_general report_general;
struct smp_response_report_manufacturer_information report_manufacturer_information;
struct smp_response_discover discover;
struct smp_response_report_phy_sata report_phy_sata;
struct smp_response_vendor_specific vendor_specific_response;
};
/**
* struct smp_response - This structure simply unionizes the existing response
* structures into a common response type.
*
*
*/
struct smp_response {
struct smp_response_header header;
union smp_response_body response;
};
/* 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_ */

View File

@ -0,0 +1,95 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SAT_H_
#define _SAT_H_
/**
* 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.
*
*
*/
/**
*
*
* 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_ */

View File

@ -0,0 +1,280 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SATA_H_
#define _SATA_H_
#include <linux/types.h>
/**
* 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.
*
*
*/
/**
*
*
* 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 - 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.
*
*
*/
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;
};
/**
* struct sata_fis_reg_h2d - This is the definition for a SATA Host to Device
* Register FIS.
*
*
*/
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 */
};
/**
* struct sata_fis_reg_d2h - SATA Device To Host FIS
*
*
*/
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;
};
/**
*
*
* Status field bit definitions
*/
#define SATA_FIS_STATUS_DEVBITS_MASK (0x77)
/**
* struct sata_fis_set_dev_bits - SATA Set Device Bits FIS
*
*
*/
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 */
};
/**
* struct sata_fis_dma_activate - SATA DMA Activate FIS
*
*
*/
struct sata_fis_dma_activate {
u32 fis_type:8; /* word 0 */
u32 pm_port:4;
u32 reserved0:24;
};
/**
*
*
* 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 - SATA DMA Setup FIS
*
*
*/
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 */
};
/**
* struct sata_fis_bist_activate - SATA BIST Activate FIS
*
*
*/
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 PIO Setup FIS
*/
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;
};
/**
* struct sata_fis_data - SATA Data FIS
*
*
*/
struct sata_fis_data {
u32 fis_type:8; /* word 0 */
u32 pm_port:4;
u32 reserved0:24;
u8 data[4]; /* word 1 */
};
#endif /* _SATA_H_ */

View File

@ -0,0 +1,474 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* 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 - 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.
*
*
*/
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,
};
/**
* enum _SCSI_TASK_MGMT_RESPONSE_CODES - This enumeration contains all of the
* SCSI task management response codes.
*
*
*/
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
};
/**
* enum _SCSI_SENSE_RESPONSE_CODE - this enumeration depicts the types of sense
* data responses as per SPC-3.
*
*
*/
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
};
/*
* 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
/**
*
*
* 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
/**
*
*
* 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_INVALID_FIELD_IN_PARM_LIST 0x26
#define SCSI_ASC_WRITE_PROTECTED 0x27
#define SCSI_ASC_NOT_READY_TO_READY_CHANGE 0x28
#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_ATA_DEVICE_FEATURE_NOT_ENABLED 0x67
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* SCSI_SERVICE_ACTION_IN_CODES Service action in operations.
*/
#define SCSI_SERVICE_ACTION_IN_CODES_READ_CAPACITY_16 0x10
#define SCSI_SERVICE_ACTION_MASK 0x1f
/**
*
*
* SCSI_MAINTENANCE_IN_SERVICE_ACTION_CODES MAINTENANCE IN service action codes.
*/
#define SCSI_REPORT_TASK_MGMT 0x0D
#define SCSI_REPORT_OP_CODES 0x0C
/**
*
*
* 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
/**
*
*
* 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 0xF0
#define SCSI_MODE_SELECT_MODE_PAGE_0A_UA_SWP 0x38
#define SCSI_MODE_SELECT_MODE_PAGE_0A_TAS_AUTO 0x47
#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
/**
*
*
* 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
/**
*
*
* 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
/**
*
*
* 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_ */

View File

@ -0,0 +1,156 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SATI_DEVICE_H_
#define _SATI_DEVICE_H_
/**
* 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 "sati_types.h"
#include "intel_ata.h"
/**
* enum _SATI_DEVICE_STATE - This enumeration depicts the various states
* possible for the a translation remote device object.
*
*
*/
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_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
/**
* struct sati_device - The SATI_DEVICE structure define the state of the
* remote device with respect to translation.
*
*
*/
struct sati_device {
/**
* This field simply dictates the state of the SATI device.
*/
enum 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;
};
void sati_device_construct(
struct sati_device *device,
bool is_ncq_enabled,
u8 max_ncq_depth);
void sati_device_update_capabilities(
struct sati_device *device,
struct ata_identify_device_data *identify);
#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */

View File

@ -0,0 +1,304 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SATI_TRANSLATOR_SEQUENCE_H_
#define _SATI_TRANSLATOR_SEQUENCE_H_
/**
* 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 "sati_device.h"
/**
* enum _SATI_TRANSLATOR_SEQUENCE_TYPE - This enumeration defines the possible
* sequence types for the translator.
*
*
*/
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_BLOCK_DEVICE,
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_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_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_START_STOP_UNIT,
SATI_SEQUENCE_REASSIGN_BLOCKS,
/* SCSI Task Requests sequences */
SATI_SEQUENCE_LUN_RESET,
SATI_SEQUENCE_REQUEST_SENSE_SMART_RETURN_STATUS,
SATI_SEQUENCE_REQUEST_SENSE_CHECK_POWER_MODE,
SATI_SEQUENCE_WRITE_LONG
};
#define SATI_SEQUENCE_TYPE_READ_MIN SATI_SEQUENCE_READ_6
#define SATI_SEQUENCE_TYPE_READ_MAX SATI_SEQUENCE_READ_16
/**
*
*
* 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
/**
*
*
* 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 - 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 - This structure contains all
* of the current processing states for processing reassign block command's
* parameter fields.
*
*
*/
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;
};
#define SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH 12
/**
* struct sati_atapi_data - The SATI_ATAPI_DATA structure is for sati atapi IO
* specific data.
*
*
*/
struct sati_atapi_data {
u8 request_sense_cdb[SATI_ATAPI_REQUEST_SENSE_CDB_LENGTH];
};
/**
* struct sati_translator_sequence - This structure contains all of the
* translation information associated with a particular request.
*
*
*/
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 specifies the remote device context for which this
* translator sequence is destined.
*/
struct sati_device *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;
struct sati_reassign_blocks_processing_state reassign_blocks_process_state;
SATI_MODE_SELECT_PROCESSING_STATE_T process_state;
struct sati_atapi_data sati_atapi_data;
} command_specific_data;
};
#endif /* _SATI_TRANSLATOR_SEQUENCE_H_ */

View File

@ -0,0 +1,145 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SATI_TYPES_H_
#define _SATI_TYPES_H_
/**
* This file contains various type definitions to be utilized with SCSI to ATA
* Translation Implementation.
*
*
*/
/**
* enum _SATI_STATUS - This enumeration defines the possible return values from
* the SATI translation methods.
*
*
*/
enum sati_status {
/**
* This indicates that the translation was supported and occurred
* without error.
*/
SATI_SUCCESS,
/**
* 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
};
#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_ */

View File

@ -0,0 +1,306 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_CONTROLLER_H_
#define _SCI_BASE_CONTROLLER_H_
#include "intel_sas.h"
#include "sci_controller_constants.h"
#include "sci_base_state.h"
#include "sci_base_memory_descriptor_list.h"
#include "sci_base_state_machine.h"
#include "sci_object.h"
struct sci_base_memory_descriptor_list;
/**
* enum sci_base_controller_states - This enumeration depicts all the states
* for the common controller state machine.
*
*
*/
enum sci_base_controller_states {
/**
* Simply the initial state for the base controller state machine.
*/
SCI_BASE_CONTROLLER_STATE_INITIAL = 0,
/**
* This state indicates that the controller is reset. The memory for
* the controller is in it's initial state, but the controller requires
* initialization.
* This state is entered from the INITIAL state.
* This state is entered from the RESETTING state.
*/
SCI_BASE_CONTROLLER_STATE_RESET,
/**
* This state is typically an action state that indicates the controller
* is in the process of initialization. In this state no new IO operations
* are permitted.
* This state is entered from the RESET state.
*/
SCI_BASE_CONTROLLER_STATE_INITIALIZING,
/**
* This state indicates that the controller has been successfully
* initialized. In this state no new IO operations are permitted.
* This state is entered from the INITIALIZING state.
*/
SCI_BASE_CONTROLLER_STATE_INITIALIZED,
/**
* This state indicates the the controller is in the process of becoming
* ready (i.e. starting). In this state no new IO operations are permitted.
* This state is entered from the INITIALIZED state.
*/
SCI_BASE_CONTROLLER_STATE_STARTING,
/**
* This state indicates the controller is now ready. Thus, the user
* is able to perform IO operations on the controller.
* This state is entered from the STARTING state.
*/
SCI_BASE_CONTROLLER_STATE_READY,
/**
* This state is typically an action state that indicates the controller
* is in the process of resetting. Thus, the user is unable to perform
* IO operations on the controller. A reset is considered destructive in
* most cases.
* This state is entered from the READY state.
* This state is entered from the FAILED state.
* This state is entered from the STOPPED state.
*/
SCI_BASE_CONTROLLER_STATE_RESETTING,
/**
* This state indicates that the controller is in the process of stopping.
* In this state no new IO operations are permitted, but existing IO
* operations are allowed to complete.
* This state is entered from the READY state.
*/
SCI_BASE_CONTROLLER_STATE_STOPPING,
/**
* This state indicates that the controller has successfully been stopped.
* In this state no new IO operations are permitted.
* This state is entered from the STOPPING state.
*/
SCI_BASE_CONTROLLER_STATE_STOPPED,
/**
* This state indicates that the controller could not successfully be
* initialized. In this state no new IO operations are permitted.
* This state is entered from the INITIALIZING state.
* This state is entered from the STARTING state.
* This state is entered from the STOPPING state.
* This state is entered from the RESETTING state.
*/
SCI_BASE_CONTROLLER_STATE_FAILED,
SCI_BASE_CONTROLLER_MAX_STATES
};
/**
* struct sci_base_controller - The base controller object abstracts the fields
* common to all SCI controller objects.
*
*
*/
struct sci_base_controller {
/**
* The field specifies that the parent object for the base controller
* is the base object itself.
*/
struct sci_base_object parent;
/**
* This field points to the memory descriptor list associated with this
* controller. The MDL indicates the memory requirements necessary for
* this controller object.
*/
struct sci_base_memory_descriptor_list mdl;
/**
* This field contains the information for the base controller state
* machine.
*/
struct sci_base_state_machine state_machine;
};
/* Forward declarations */
struct sci_base_remote_device;
struct sci_base_request;
typedef enum sci_status
(*sci_base_controller_handler_t)(struct sci_base_controller *);
typedef enum sci_status
(*sci_base_controller_timed_handler_t)(struct sci_base_controller *, u32);
typedef enum sci_status
(*sci_base_controller_request_handler_t)(struct sci_base_controller *,
struct sci_base_remote_device *,
struct sci_base_request *);
typedef enum sci_status
(*sci_base_controller_start_request_handler_t)(struct sci_base_controller *,
struct sci_base_remote_device *,
struct sci_base_request *, u16);
/**
* struct sci_base_controller_state_handler - This structure contains all of
* the state handler methods common to base controller state machines.
* Handler methods provide the ability to change the behavior for user
* requests or transitions depending on the state the machine is in.
*
*
*/
struct sci_base_controller_state_handler {
/**
* The start_handler specifies the method invoked when a user attempts to
* start a controller.
*/
sci_base_controller_timed_handler_t start;
/**
* The stop_handler specifies the method invoked when a user attempts to
* stop a controller.
*/
sci_base_controller_timed_handler_t stop;
/**
* The reset_handler specifies the method invoked when a user attempts to
* reset a controller.
*/
sci_base_controller_handler_t reset;
/**
* The initialize_handler specifies the method invoked when a user
* attempts to initialize a controller.
*/
sci_base_controller_handler_t initialize;
/**
* The start_io_handler specifies the method invoked when a user
* attempts to start an IO request for a controller.
*/
sci_base_controller_start_request_handler_t start_io;
/**
* The complete_io_handler specifies the method invoked when a user
* attempts to complete an IO request for a controller.
*/
sci_base_controller_request_handler_t complete_io;
/**
* The continue_io_handler specifies the method invoked when a user
* attempts to continue an IO request for a controller.
*/
sci_base_controller_request_handler_t continue_io;
/**
* The start_task_handler specifies the method invoked when a user
* attempts to start a task management request for a controller.
*/
sci_base_controller_start_request_handler_t start_task;
/**
* The complete_task_handler specifies the method invoked when a user
* attempts to complete a task management request for a controller.
*/
sci_base_controller_request_handler_t complete_task;
};
/**
* sci_base_controller_construct() - Construct the base controller
* @this_controller: This parameter specifies the base controller to be
* constructed.
* @state_table: This parameter specifies the table of state definitions to be
* utilized for the controller state machine.
* @mde_array: This parameter specifies the array of memory descriptor entries
* to be managed by this list.
* @mde_array_length: This parameter specifies the size of the array of entries.
* @next_mdl: This parameter specifies a subsequent MDL object to be managed by
* this MDL object.
* @oem_parameters: This parameter specifies the original equipment
* manufacturer parameters to be utilized by this controller object.
*
*/
static inline void sci_base_controller_construct(
struct sci_base_controller *scic_base,
const struct sci_base_state *state_table,
struct sci_physical_memory_descriptor *mdes,
u32 mde_count,
struct sci_base_memory_descriptor_list *next_mdl)
{
scic_base->parent.private = NULL;
sci_base_state_machine_construct(
&scic_base->state_machine,
&scic_base->parent,
state_table,
SCI_BASE_CONTROLLER_STATE_INITIAL
);
sci_base_mdl_construct(&scic_base->mdl, mdes, mde_count, next_mdl);
sci_base_state_machine_start(&scic_base->state_machine);
}
#endif /* _SCI_BASE_CONTROLLER_H_ */

View File

@ -0,0 +1,159 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the base implementation for the memory descriptor list.
* This is currently comprised of MDL iterator methods.
*
*
*/
#include "sci_environment.h"
#include "sci_base_memory_descriptor_list.h"
/*
* ******************************************************************************
* * P U B L I C M E T H O D S
* ****************************************************************************** */
void sci_mdl_first_entry(
struct sci_base_memory_descriptor_list *base_mdl)
{
base_mdl->next_index = 0;
/*
* If this MDL is managing another MDL, then recursively rewind that MDL
* object as well. */
if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
sci_mdl_first_entry(base_mdl->next_mdl);
}
void sci_mdl_next_entry(
struct sci_base_memory_descriptor_list *base_mdl)
{
/*
* If there is at least one more entry left in the array, then change
* the next pointer to it. */
if (base_mdl->next_index < base_mdl->length)
base_mdl->next_index++;
else if (base_mdl->next_index == base_mdl->length) {
/*
* This MDL has exhausted it's set of entries. If this MDL is managing
* another MDL, then start iterating through that MDL. */
if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
sci_mdl_next_entry(base_mdl->next_mdl);
}
}
struct sci_physical_memory_descriptor *sci_mdl_get_current_entry(
struct sci_base_memory_descriptor_list *base_mdl)
{
if (base_mdl->next_index < base_mdl->length)
return &base_mdl->mde_array[base_mdl->next_index];
else if (base_mdl->next_index == base_mdl->length) {
/*
* This MDL has exhausted it's set of entries. If this MDL is managing
* another MDL, then return it's current entry. */
if (base_mdl->next_mdl != SCI_INVALID_HANDLE)
return sci_mdl_get_current_entry(base_mdl->next_mdl);
}
return NULL;
}
/*
* ******************************************************************************
* * P R O T E C T E D M E T H O D S
* ****************************************************************************** */
void sci_base_mdl_construct(
struct sci_base_memory_descriptor_list *mdl,
struct sci_physical_memory_descriptor *mde_array,
u32 mde_array_length,
struct sci_base_memory_descriptor_list *next_mdl)
{
mdl->length = mde_array_length;
mdl->mde_array = mde_array;
mdl->next_index = 0;
mdl->next_mdl = next_mdl;
}
/* --------------------------------------------------------------------------- */
bool sci_base_mde_is_valid(
struct sci_physical_memory_descriptor *mde,
u32 alignment,
u32 size,
u16 attributes)
{
/* Only need the lower 32 bits to ensure alignment is met. */
u32 physical_address = lower_32_bits(mde->physical_address);
if (
((((unsigned long)mde->virtual_address) & (alignment - 1)) != 0)
|| ((physical_address & (alignment - 1)) != 0)
|| (mde->constant_memory_alignment != alignment)
|| (mde->constant_memory_size != size)
|| (mde->virtual_address == NULL)
|| (mde->constant_memory_attributes != attributes)
) {
return false;
}
return true;
}

View File

@ -0,0 +1,155 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
#define _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_
/**
* This file contains the protected interface structures, constants and
* interface methods for the struct sci_base_memory_descriptor_list object.
*
*
*/
#include "sci_types.h"
#include "sci_memory_descriptor_list.h"
/**
* struct sci_base_memory_descriptor_list - This structure contains all of the
* fields necessary to implement a simple stack for managing the list of
* available controller indices.
*
*
*/
struct sci_base_memory_descriptor_list {
/**
* This field indicates the length of the memory descriptor entry array.
*/
u32 length;
/**
* This field is utilized to provide iterator pattern functionality.
* It indicates the index of the next memory descriptor in the iteration.
*/
u32 next_index;
/**
* This field will point to the list of memory descriptors.
*/
struct sci_physical_memory_descriptor *mde_array;
/**
* This field simply allows a user to chain memory descriptor lists
* together if desired. This field will be initialized to
* SCI_INVALID_HANDLE.
*/
struct sci_base_memory_descriptor_list *next_mdl;
};
/**
* sci_base_mdl_construct() - This method is invoked to construct an memory
* descriptor list. It initializes the fields of the MDL.
* @mdl: This parameter specifies the memory descriptor list to be constructed.
* @mde_array: This parameter specifies the array of memory descriptor entries
* to be managed by this list.
* @mde_array_length: This parameter specifies the size of the array of entries.
* @next_mdl: This parameter specifies a subsequent MDL object to be managed by
* this MDL object.
*
* none.
*/
void sci_base_mdl_construct(
struct sci_base_memory_descriptor_list *mdl,
struct sci_physical_memory_descriptor *mde_array,
u32 mde_array_length,
struct sci_base_memory_descriptor_list *next_mdl);
/**
* sci_base_mde_construct() -
*
* This macro constructs an memory descriptor entry with the given alignment
* and size
*/
#define sci_base_mde_construct(mde, alignment, size, attributes) \
{ \
(mde)->constant_memory_alignment = (alignment); \
(mde)->constant_memory_size = (size); \
(mde)->constant_memory_attributes = (attributes); \
}
/**
* sci_base_mde_is_valid() - This method validates that the memory descriptor
* is correctly filled out by the SCI User
* @mde: This parameter is the mde entry to validate
* @alignment: This parameter specifies the expected alignment of the memory
* for the mde.
* @size: This parameter specifies the memory size expected for the mde its
* value should not have been changed by the SCI User.
* @attributes: This parameter specifies the attributes for the memory
* descriptor provided.
*
* bool This method returns an indication as to whether the supplied MDE is
* valid or not. true The MDE is valid. false The MDE is not valid.
*/
bool sci_base_mde_is_valid(
struct sci_physical_memory_descriptor *mde,
u32 alignment,
u32 size,
u16 attributes);
#endif /* _SCI_BASE_MEMORY_DESCRIPTOR_LIST_H_ */

View File

@ -0,0 +1,205 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_PHY_H_
#define _SCI_BASE_PHY_H_
/**
* This file contains all of the structures, constants, and methods common to
* all phy object definitions.
*
*
*/
#include "sci_base_state_machine.h"
/**
* enum sci_base_phy_states - This enumeration depicts the standard states
* common to all phy state machine implementations.
*
*
*/
enum sci_base_phy_states {
/**
* Simply the initial state for the base domain state machine.
*/
SCI_BASE_PHY_STATE_INITIAL,
/**
* This state indicates that the phy has successfully been stopped.
* In this state no new IO operations are permitted on this phy.
* This state is entered from the INITIAL state.
* This state is entered from the STARTING state.
* This state is entered from the READY state.
* This state is entered from the RESETTING state.
*/
SCI_BASE_PHY_STATE_STOPPED,
/**
* This state indicates that the phy is in the process of becomming
* ready. In this state no new IO operations are permitted on this phy.
* This state is entered from the STOPPED state.
* This state is entered from the READY state.
* This state is entered from the RESETTING state.
*/
SCI_BASE_PHY_STATE_STARTING,
/**
* This state indicates the the phy is now ready. Thus, the user
* is able to perform IO operations utilizing this phy as long as it
* is currently part of a valid port.
* This state is entered from the STARTING state.
*/
SCI_BASE_PHY_STATE_READY,
/**
* This state indicates that the phy is in the process of being reset.
* In this state no new IO operations are permitted on this phy.
* This state is entered from the READY state.
*/
SCI_BASE_PHY_STATE_RESETTING,
/**
* Simply the final state for the base phy state machine.
*/
SCI_BASE_PHY_STATE_FINAL,
SCI_BASE_PHY_MAX_STATES
};
/**
* struct sci_base_phy - This structure defines all of the fields common to PHY
* objects.
*
*
*/
struct sci_base_phy {
/**
* This field depicts the parent object (struct sci_base_object) for the phy.
*/
struct sci_base_object parent;
/**
* This field contains the information for the base phy state machine.
*/
struct sci_base_state_machine state_machine;
};
typedef enum sci_status (*SCI_BASE_PHY_HANDLER_T)(
struct sci_base_phy *
);
/**
* struct sci_base_phy_state_handler - This structure contains all of the state
* handler methods common to base phy state machines. Handler methods
* provide the ability to change the behavior for user requests or
* transitions depending on the state the machine is in.
*
*
*/
struct sci_base_phy_state_handler {
/**
* The start_handler specifies the method invoked when there is an
* attempt to start a phy.
*/
SCI_BASE_PHY_HANDLER_T start_handler;
/**
* The stop_handler specifies the method invoked when there is an
* attempt to stop a phy.
*/
SCI_BASE_PHY_HANDLER_T stop_handler;
/**
* The reset_handler specifies the method invoked when there is an
* attempt to reset a phy.
*/
SCI_BASE_PHY_HANDLER_T reset_handler;
/**
* The destruct_handler specifies the method invoked when attempting to
* destruct a phy.
*/
SCI_BASE_PHY_HANDLER_T destruct_handler;
};
/**
* sci_base_phy_construct() - Construct the base phy
* @this_phy: This parameter specifies the base phy to be constructed.
* @state_table: This parameter specifies the table of state definitions to be
* utilized for the phy state machine.
*
*/
static inline void sci_base_phy_construct(
struct sci_base_phy *base_phy,
const struct sci_base_state *state_table)
{
base_phy->parent.private = NULL;
sci_base_state_machine_construct(
&base_phy->state_machine,
&base_phy->parent,
state_table,
SCI_BASE_PHY_STATE_INITIAL
);
sci_base_state_machine_start(
&base_phy->state_machine
);
}
#endif /* _SCI_BASE_PHY_H_ */

View File

@ -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.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_PORT_H_
#define _SCI_BASE_PORT_H_
#include "sci_base_state_machine.h"
#include "sci_object.h"
/**
* enum sci_base_port_states - This enumeration depicts all the states for the
* common port state machine.
*
*
*/
enum sci_base_port_states {
/**
* This state indicates that the port has successfully been stopped.
* In this state no new IO operations are permitted.
* This state is entered from the STOPPING state.
*/
SCI_BASE_PORT_STATE_STOPPED,
/**
* This state indicates that the port is in the process of stopping.
* In this state no new IO operations are permitted, but existing IO
* operations are allowed to complete.
* This state is entered from the READY state.
*/
SCI_BASE_PORT_STATE_STOPPING,
/**
* This state indicates the port is now ready. Thus, the user is
* able to perform IO operations on this port.
* This state is entered from the STARTING state.
*/
SCI_BASE_PORT_STATE_READY,
/**
* This state indicates the port is in the process of performing a hard
* reset. Thus, the user is unable to perform IO operations on this
* port.
* This state is entered from the READY state.
*/
SCI_BASE_PORT_STATE_RESETTING,
/**
* This state indicates the port has failed a reset request. This state
* is entered when a port reset request times out.
* This state is entered from the RESETTING state.
*/
SCI_BASE_PORT_STATE_FAILED,
SCI_BASE_PORT_MAX_STATES
};
/**
* struct sci_base_port - The base port object abstracts the fields common to
* all SCI port objects.
*
*
*/
struct sci_base_port {
/**
* The field specifies that the parent object for the base controller
* is the base object itself.
*/
struct sci_base_object parent;
/**
* This field contains the information for the base port state machine.
*/
struct sci_base_state_machine state_machine;
};
struct sci_base_phy;
typedef enum sci_status (*SCI_BASE_PORT_HANDLER_T)(
struct sci_base_port *
);
typedef enum sci_status (*SCI_BASE_PORT_PHY_HANDLER_T)(
struct sci_base_port *,
struct sci_base_phy *
);
typedef enum sci_status (*SCI_BASE_PORT_RESET_HANDLER_T)(
struct sci_base_port *,
u32 timeout
);
/**
* struct sci_base_port_state_handler - This structure contains all of the
* state handler methods common to base port state machines. Handler
* methods provide the ability to change the behavior for user requests or
* transitions depending on the state the machine is in.
*
*
*/
struct sci_base_port_state_handler {
/**
* The start_handler specifies the method invoked when a user attempts to
* start a port.
*/
SCI_BASE_PORT_HANDLER_T start_handler;
/**
* The stop_handler specifies the method invoked when a user attempts to
* stop a port.
*/
SCI_BASE_PORT_HANDLER_T stop_handler;
/**
* The destruct_handler specifies the method invoked when attempting to
* destruct a port.
*/
SCI_BASE_PORT_HANDLER_T destruct_handler;
/**
* The reset_handler specifies the method invoked when a user attempts to
* hard reset a port.
*/
SCI_BASE_PORT_RESET_HANDLER_T reset_handler;
/**
* The add_phy_handler specifies the method invoked when a user attempts to
* add another phy into the port.
*/
SCI_BASE_PORT_PHY_HANDLER_T add_phy_handler;
/**
* The remove_phy_handler specifies the method invoked when a user
* attempts to remove a phy from the port.
*/
SCI_BASE_PORT_PHY_HANDLER_T remove_phy_handler;
};
/**
* sci_base_port_construct() - Construct the base port object
* @this_port: This parameter specifies the base port to be constructed.
* @state_table: This parameter specifies the table of state definitions to be
* utilized for the domain state machine.
*
*/
void sci_base_port_construct(
struct sci_base_port *this_port,
const struct sci_base_state *state_table);
#endif /* _SCI_BASE_PORT_H_ */

View File

@ -0,0 +1,277 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_REMOTE_DEVICE_H_
#define _SCI_BASE_REMOTE_DEVICE_H_
/**
* This file contains all of the structures, constants, and methods common to
* all remote device object definitions.
*
*
*/
#include "sci_base_state_machine.h"
struct sci_base_request;
/**
* enum sci_base_remote_device_states - This enumeration depicts all the states
* for the common remote device state machine.
*
*
*/
enum sci_base_remote_device_states {
/**
* Simply the initial state for the base remote device state machine.
*/
SCI_BASE_REMOTE_DEVICE_STATE_INITIAL,
/**
* This state indicates that the remote device has successfully been
* stopped. In this state no new IO operations are permitted.
* This state is entered from the INITIAL state.
* This state is entered from the STOPPING state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_STOPPED,
/**
* This state indicates the the remote device is in the process of
* becoming ready (i.e. starting). In this state no new IO operations
* are permitted.
* This state is entered from the STOPPED state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_STARTING,
/**
* This state indicates the remote device is now ready. Thus, the user
* is able to perform IO operations on the remote device.
* This state is entered from the STARTING state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_READY,
/**
* This state indicates that the remote device is in the process of
* stopping. In this state no new IO operations are permitted, but
* existing IO operations are allowed to complete.
* This state is entered from the READY state.
* This state is entered from the FAILED state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_STOPPING,
/**
* This state indicates that the remote device has failed.
* In this state no new IO operations are permitted.
* This state is entered from the INITIALIZING state.
* This state is entered from the READY state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_FAILED,
/**
* This state indicates the device is being reset.
* In this state no new IO operations are permitted.
* This state is entered from the READY state.
*/
SCI_BASE_REMOTE_DEVICE_STATE_RESETTING,
/**
* Simply the final state for the base remote device state machine.
*/
SCI_BASE_REMOTE_DEVICE_STATE_FINAL,
SCI_BASE_REMOTE_DEVICE_MAX_STATES
};
/**
* struct sci_base_remote_device - The base remote device object abstracts the
* fields common to all SCI remote device objects.
*
*
*/
struct sci_base_remote_device {
/**
* The field specifies that the parent object for the base remote
* device is the base object itself.
*/
struct sci_base_object parent;
/**
* This field contains the information for the base remote device state
* machine.
*/
struct sci_base_state_machine state_machine;
};
typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HANDLER_T)(
struct sci_base_remote_device *
);
typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T)(
struct sci_base_remote_device *,
struct sci_base_request *
);
typedef enum sci_status (*SCI_BASE_REMOTE_DEVICE_HIGH_PRIORITY_REQUEST_COMPLETE_HANDLER_T)(
struct sci_base_remote_device *,
struct sci_base_request *,
void *,
enum sci_io_status
);
/**
* struct sci_base_remote_device_state_handler - This structure contains all of
* the state handler methods common to base remote device state machines.
* Handler methods provide the ability to change the behavior for user
* requests or transitions depending on the state the machine is in.
*
*
*/
struct sci_base_remote_device_state_handler {
/**
* The start_handler specifies the method invoked when a user attempts to
* start a remote device.
*/
SCI_BASE_REMOTE_DEVICE_HANDLER_T start_handler;
/**
* The stop_handler specifies the method invoked when a user attempts to
* stop a remote device.
*/
SCI_BASE_REMOTE_DEVICE_HANDLER_T stop_handler;
/**
* The fail_handler specifies the method invoked when a remote device
* failure has occurred. A failure may be due to an inability to
* initialize/configure the device.
*/
SCI_BASE_REMOTE_DEVICE_HANDLER_T fail_handler;
/**
* The destruct_handler specifies the method invoked when attempting to
* destruct a remote device.
*/
SCI_BASE_REMOTE_DEVICE_HANDLER_T destruct_handler;
/**
* The reset handler specifies the method invloked when requesting to reset a
* remote device.
*/
SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_handler;
/**
* The reset complete handler specifies the method invloked when reporting
* that a reset has completed to the remote device.
*/
SCI_BASE_REMOTE_DEVICE_HANDLER_T reset_complete_handler;
/**
* The start_io_handler specifies the method invoked when a user
* attempts to start an IO request for a remote device.
*/
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_io_handler;
/**
* The complete_io_handler specifies the method invoked when a user
* attempts to complete an IO request for a remote device.
*/
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_io_handler;
/**
* The continue_io_handler specifies the method invoked when a user
* attempts to continue an IO request for a remote device.
*/
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T continue_io_handler;
/**
* The start_task_handler specifies the method invoked when a user
* attempts to start a task management request for a remote device.
*/
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T start_task_handler;
/**
* The complete_task_handler specifies the method invoked when a user
* attempts to complete a task management request for a remote device.
*/
SCI_BASE_REMOTE_DEVICE_REQUEST_HANDLER_T complete_task_handler;
};
/**
* sci_base_remote_device_construct() - Construct the base remote device
* @this_remote_device: This parameter specifies the base remote device to be
* constructed.
* @state_table: This parameter specifies the table of state definitions to be
* utilized for the remote device state machine.
*
*/
static inline void sci_base_remote_device_construct(
struct sci_base_remote_device *base_dev,
const struct sci_base_state *state_table)
{
base_dev->parent.private = NULL;
sci_base_state_machine_construct(
&base_dev->state_machine,
&base_dev->parent,
state_table,
SCI_BASE_REMOTE_DEVICE_STATE_INITIAL
);
sci_base_state_machine_start(
&base_dev->state_machine
);
}
#endif /* _SCI_BASE_REMOTE_DEVICE_H_ */

View File

@ -0,0 +1,195 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_REQUST_H_
#define _SCI_BASE_REQUST_H_
/**
* This file contains all of the constants, types, and method declarations for
* the SCI base IO and task request objects.
*
*
*/
#include "sci_base_state_machine.h"
/**
* enum sci_base_request_states - This enumeration depicts all the states for
* the common request state machine.
*
*
*/
enum sci_base_request_states {
/**
* Simply the initial state for the base request state machine.
*/
SCI_BASE_REQUEST_STATE_INITIAL,
/**
* This state indicates that the request has been constructed. This state
* is entered from the INITIAL state.
*/
SCI_BASE_REQUEST_STATE_CONSTRUCTED,
/**
* This state indicates that the request has been started. This state is
* entered from the CONSTRUCTED state.
*/
SCI_BASE_REQUEST_STATE_STARTED,
/**
* This state indicates that the request has completed.
* This state is entered from the STARTED state. This state is entered from
* the ABORTING state.
*/
SCI_BASE_REQUEST_STATE_COMPLETED,
/**
* This state indicates that the request is in the process of being
* terminated/aborted.
* This state is entered from the CONSTRUCTED state.
* This state is entered from the STARTED state.
*/
SCI_BASE_REQUEST_STATE_ABORTING,
/**
* Simply the final state for the base request state machine.
*/
SCI_BASE_REQUEST_STATE_FINAL,
};
/**
* struct sci_base_request - The base request object abstracts the fields
* common to all SCI IO and task request objects.
*
*
*/
struct sci_base_request {
/**
* The field specifies that the parent object for the base request is the
* base object itself.
*/
struct sci_base_object parent;
/**
* This field contains the information for the base request state machine.
*/
struct sci_base_state_machine state_machine;
};
typedef enum sci_status (*SCI_BASE_REQUEST_HANDLER_T)(
struct sci_base_request *this_request
);
/**
* struct sci_base_request_state_handler - This structure contains all of the
* state handler methods common to base IO and task request state machines.
* Handler methods provide the ability to change the behavior for user
* requests or transitions depending on the state the machine is in.
*
*
*/
struct sci_base_request_state_handler {
/**
* The start_handler specifies the method invoked when a user attempts to
* start a request.
*/
SCI_BASE_REQUEST_HANDLER_T start_handler;
/**
* The abort_handler specifies the method invoked when a user attempts to
* abort a request.
*/
SCI_BASE_REQUEST_HANDLER_T abort_handler;
/**
* The complete_handler specifies the method invoked when a user attempts to
* complete a request.
*/
SCI_BASE_REQUEST_HANDLER_T complete_handler;
/**
* The destruct_handler specifies the method invoked when a user attempts to
* destruct a request.
*/
SCI_BASE_REQUEST_HANDLER_T destruct_handler;
};
/**
* sci_base_request_construct() - Construct the base request.
* @this_request: This parameter specifies the base request to be constructed.
* @state_table: This parameter specifies the table of state definitions to be
* utilized for the request state machine.
*
*/
static inline void sci_base_request_construct(
struct sci_base_request *base_req,
const struct sci_base_state *my_state_table)
{
base_req->parent.private = NULL;
sci_base_state_machine_construct(
&base_req->state_machine,
&base_req->parent,
my_state_table,
SCI_BASE_REQUEST_STATE_INITIAL
);
sci_base_state_machine_start(
&base_req->state_machine
);
}
#endif /* _SCI_BASE_REQUST_H_ */

View File

@ -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.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_STATE_H_
#define _SCI_BASE_STATE_H_
#include "sci_object.h"
typedef void (*SCI_BASE_STATE_HANDLER_T)(
void
);
typedef void (*SCI_STATE_TRANSITION_T)(
struct sci_base_object *base_object
);
/**
* struct sci_base_state - The base state object abstracts the fields common to
* all state objects defined in SCI.
*
*
*/
struct sci_base_state {
/**
* This field is a function pointer that defines the method to be
* invoked when the state is entered.
*/
SCI_STATE_TRANSITION_T enter_state;
/**
* This field is a function pointer that defines the method to be
* invoked when the state is exited.
*/
SCI_STATE_TRANSITION_T exit_state;
};
#endif /* _SCI_BASE_STATE_H_ */

View File

@ -0,0 +1,182 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains all of the functionality common to all state machine
* object implementations.
*
*
*/
#include "sci_base_state_machine.h"
static void sci_state_machine_exit_state(struct sci_base_state_machine *sm)
{
u32 state = sm->current_state_id;
SCI_STATE_TRANSITION_T exit = sm->state_table[state].exit_state;
if (exit)
exit(sm->state_machine_owner);
}
static void sci_state_machine_enter_state(struct sci_base_state_machine *sm)
{
u32 state = sm->current_state_id;
SCI_STATE_TRANSITION_T enter = sm->state_table[state].enter_state;
if (enter)
enter(sm->state_machine_owner);
}
/*
* ******************************************************************************
* * P R O T E C T E D M E T H O D S
* ****************************************************************************** */
/**
* This method will set the initial state and state table for the state
* machine. The caller should follow this request with the initialize
* request to cause the state machine to start.
* @sm: This parameter provides the state machine object to be
* constructed.
* @state_machine_owner: This parameter indicates the object that is owns the
* state machine being constructed.
* @state_table: This parameter specifies the table of state objects that is
* managed by this state machine.
* @initial_state: This parameter specifies the value of the initial state for
* this state machine.
*
*/
void sci_base_state_machine_construct(struct sci_base_state_machine *sm,
struct sci_base_object *owner,
const struct sci_base_state *state_table,
u32 initial_state)
{
sm->state_machine_owner = owner;
sm->initial_state_id = initial_state;
sm->previous_state_id = initial_state;
sm->current_state_id = initial_state;
sm->state_table = state_table;
}
/**
* This method will cause the state machine to enter the initial state.
* @sm: This parameter specifies the state machine that is to
* be started.
*
* sci_base_state_machine_construct() for how to set the initial state none
*/
void sci_base_state_machine_start(struct sci_base_state_machine *sm)
{
sm->current_state_id = sm->initial_state_id;
#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
sci_base_subject_notify(&sm->parent);
#endif
sci_state_machine_enter_state(sm);
}
/**
* This method will cause the state machine to exit it's current state only.
* @sm: This parameter specifies the state machine that is to
* be stopped.
*
*/
void sci_base_state_machine_stop(
struct sci_base_state_machine *sm)
{
sci_state_machine_exit_state(sm);
#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
sci_base_subject_notify(&sm->parent);
#endif
}
/**
* This method performs an update to the current state of the state machine.
* @sm: This parameter specifies the state machine for which
* the caller wishes to perform a state change.
* @next_state: This parameter specifies the new state for the state machine.
*
*/
void sci_base_state_machine_change_state(
struct sci_base_state_machine *sm,
u32 next_state)
{
sci_state_machine_exit_state(sm);
sm->previous_state_id = sm->current_state_id;
sm->current_state_id = next_state;
#if defined(SCI_BASE_ENABLE_SUBJECT_NOTIFICATION)
/* Notify of the state change prior to entering the state. */
sci_base_subject_notify(&sm->parent);
#endif
sci_state_machine_enter_state(sm);
}
/**
* This method simply returns the current state of the state machine to the
* caller.
* @sm: This parameter specifies the state machine for which to
* retrieve the current state.
*
* This method returns a u32 value indicating the current state for the
* supplied state machine.
*/
u32 sci_base_state_machine_get_state(struct sci_base_state_machine *sm)
{
return sm->current_state_id;
}

View File

@ -0,0 +1,139 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_BASE_STATE_MACHINE_H_
#define _SCI_BASE_STATE_MACHINE_H_
/**
* This file contains all structures, constants, or method declarations common
* to all state machines defined in SCI.
*
*
*/
#include "sci_base_state.h"
/**
* SET_STATE_HANDLER() -
*
* This macro simply provides simplified retrieval of an objects state handler.
*/
#define SET_STATE_HANDLER(object, table, state) \
(object)->state_handlers = &(table)[(state)]
/**
* struct sci_base_state_machine - This structure defines the fields common to
* all state machines.
*
*
*/
struct sci_base_state_machine {
/**
* This field points to the start of the state machine's state table.
*/
const struct sci_base_state *state_table;
/**
* This field points to the object to which this state machine is
* associated. It serves as a cookie to be provided to the state
* enter/exit methods.
*/
struct sci_base_object *state_machine_owner;
/**
* This field simply indicates the state value for the state machine's
* initial state.
*/
u32 initial_state_id;
/**
* This field indicates the current state of the state machine.
*/
u32 current_state_id;
/**
* This field indicates the previous state of the state machine.
*/
u32 previous_state_id;
};
/*
* ******************************************************************************
* * P R O T E C T E D M E T H O D S
* ****************************************************************************** */
void sci_base_state_machine_construct(
struct sci_base_state_machine *this_state_machine,
struct sci_base_object *state_machine_owner,
const struct sci_base_state *state_table,
u32 initial_state);
void sci_base_state_machine_start(
struct sci_base_state_machine *this_state_machine);
void sci_base_state_machine_stop(
struct sci_base_state_machine *this_state_machine);
void sci_base_state_machine_change_state(
struct sci_base_state_machine *this_state_machine,
u32 next_state);
u32 sci_base_state_machine_get_state(
struct sci_base_state_machine *this_state_machine);
#endif /* _SCI_BASE_STATE_MACHINE_H_ */

View File

@ -0,0 +1,100 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_CONTROLLER_H_
#define _SCI_CONTROLLER_H_
/**
* This file contains all of the interface methods that can be called by an SCI
* user on all SCI controller objects.
*
*
*/
#include "sci_types.h"
struct sci_base_memory_descriptor_list;
struct scic_sds_controller;
#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF
/**
* sci_controller_get_memory_descriptor_list_handle() - This method simply
* returns a handle for the memory descriptor list associated with the
* supplied controller. The descriptor list provides DMA safe/capable
* memory requirements for this controller.
* @controller: This parameter specifies the controller for which to retrieve
* the DMA safe memory descriptor list.
*
* The user must adhere to the alignment requirements specified in memory
* descriptor. In situations where the operating environment does not offer
* memory allocation utilities supporting alignment, then it is the
* responsibility of the user to manually align the memory buffer for SCI.
* Thus, the user may have to allocate a larger buffer to meet the alignment.
* Additionally, the user will need to remember the actual memory allocation
* addresses in order to ensure the memory can be properly freed when necessary
* to do so. This method will return a valid handle, but the MDL may not be
* accurate until after the user has invoked the associated
* sci_controller_initialize() routine. A pointer to a physical memory
* descriptor array.
*/
struct sci_base_memory_descriptor_list *
sci_controller_get_memory_descriptor_list_handle(
struct scic_sds_controller *controller);
#endif /* _SCI_CONTROLLER_H_ */

View File

@ -0,0 +1,215 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_CONTROLLER_CONSTANTS_H_
#define _SCI_CONTROLLER_CONSTANTS_H_
/**
* This file contains constant values that change based on the type of core or
* framework being managed. These constants are exported in order to
* provide the user with information as to the bounds (i.e. how many) of
* specific objects.
*
*
*/
#ifdef SCIC_SDS_4_ENABLED
#ifndef SCI_MAX_PHYS
/**
*
*
* This constant defines the maximum number of phy objects that can be
* supported for the SCU Driver Standard (SDS) library. This is tied directly
* to silicon capabilities.
*/
#define SCI_MAX_PHYS (4)
#endif
#ifndef SCI_MAX_PORTS
/**
*
*
* This constant defines the maximum number of port objects that can be
* supported for the SCU Driver Standard (SDS) library. This is tied directly
* to silicon capabilities.
*/
#define SCI_MAX_PORTS SCI_MAX_PHYS
#endif
#ifndef SCI_MIN_SMP_PHYS
/**
*
*
* This constant defines the minimum number of SMP phy objects that can be
* supported for a single expander level. This was determined by using 36
* physical phys and room for 2 virtual phys.
*/
#define SCI_MIN_SMP_PHYS (38)
#endif
#ifndef SCI_MAX_SMP_PHYS
/**
*
*
* This constant defines the maximum number of SMP phy objects that can be
* supported for the SCU Driver Standard (SDS) library. This number can be
* increased if required.
*/
#define SCI_MAX_SMP_PHYS (384)
#endif
#ifndef SCI_MAX_REMOTE_DEVICES
/**
*
*
* This constant defines the maximum number of remote device objects that can
* be supported for the SCU Driver Standard (SDS) library. This is tied
* directly to silicon capabilities.
*/
#define SCI_MAX_REMOTE_DEVICES (256)
#endif
#ifndef SCI_MIN_REMOTE_DEVICES
/**
*
*
* This constant defines the minimum number of remote device objects that can
* be supported for the SCU Driver Standard (SDS) library. This # can be
* configured for minimum memory environments to any value less than
* SCI_MAX_REMOTE_DEVICES
*/
#define SCI_MIN_REMOTE_DEVICES (16)
#endif
#ifndef SCI_MAX_IO_REQUESTS
/**
*
*
* This constant defines the maximum number of IO request objects that can be
* supported for the SCU Driver Standard (SDS) library. This is tied directly
* to silicon capabilities.
*/
#define SCI_MAX_IO_REQUESTS (256)
#endif
#ifndef SCI_MIN_IO_REQUESTS
/**
*
*
* This constant defines the minimum number of IO request objects that can be
* supported for the SCU Driver Standard (SDS) library. This # can be
* configured for minimum memory environments to any value less than
* SCI_MAX_IO_REQUESTS.
*/
#define SCI_MIN_IO_REQUESTS (1)
#endif
#ifndef SCI_MAX_MSIX_MESSAGES
/**
*
*
* This constant defines the maximum number of MSI-X interrupt vectors/messages
* supported for an SCU hardware controller instance.
*/
#define SCI_MAX_MSIX_MESSAGES (2)
#endif
#ifndef SCI_MAX_SCATTER_GATHER_ELEMENTS
/**
*
*
* This constant defines the maximum number of Scatter-Gather Elements to be
* used by any SCI component.
*/
#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130
#endif
#ifndef SCI_MIN_SCATTER_GATHER_ELEMENTS
/**
*
*
* This constant defines the minimum number of Scatter-Gather Elements to be
* used by any SCI component.
*/
#define SCI_MIN_SCATTER_GATHER_ELEMENTS 1
#endif
#else /* SCIC_SDS_4_ENABLED */
#error "SCI Core configuration left unspecified (e.g. SCIC_SDS_4_ENABLED)"
#endif /* SCIC_SDS_4_ENABLED */
/**
*
*
* This constant defines the maximum number of controllers that can occur in a
* single silicon package.
*/
#define SCI_MAX_CONTROLLERS 2
/**
*
*
* The maximum number of supported domain objects is currently tied to the
* maximum number of support port objects.
*/
#define SCI_MAX_DOMAINS SCI_MAX_PORTS
#endif /* _SCI_CONTROLLER_CONSTANTS_H_ */

View File

@ -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.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_MEMORY_DESCRIPTOR_LIST_H_
#define _SCI_MEMORY_DESCRIPTOR_LIST_H_
/**
* This file contains all of the basic data types utilized by an SCI user or
* implementor.
*
*
*/
#include "sci_types.h"
struct sci_base_memory_descriptor_list;
/**
*
*
* SCI_MDE_ATTRIBUTES These constants depict memory attributes for the Memory
* Descriptor Entries (MDEs) contained in the MDL.
*/
#define SCI_MDE_ATTRIBUTE_CACHEABLE 0x0001
#define SCI_MDE_ATTRIBUTE_PHYSICALLY_CONTIGUOUS 0x0002
/**
* struct sci_physical_memory_descriptor - This structure defines a description
* of a memory location for the SCI implementation.
*
*
*/
struct sci_physical_memory_descriptor {
/**
* This field contains the virtual address associated with this descriptor
* element. This field shall be zero when the descriptor is retrieved from
* the SCI implementation. The user shall set this field prior
* sci_controller_start()
*/
void *virtual_address;
/**
* This field contains the physical address associated with this desciptor
* element. This field shall be zero when the descriptor is retrieved from
* the SCI implementation. The user shall set this field prior
* sci_controller_start()
*/
dma_addr_t physical_address;
/**
* This field contains the size requirement for this memory descriptor.
* A value of zero for this field indicates the end of the descriptor
* list. The value should be treated as read only for an SCI user.
*/
u32 constant_memory_size;
/**
* This field contains the alignment requirement for this memory
* descriptor. A value of zero for this field indicates the end of the
* descriptor list. All other values indicate the number of bytes to
* achieve the necessary alignment. The value should be treated as
* read only for an SCI user.
*/
u32 constant_memory_alignment;
/**
* This field contains an indication regarding the desired memory
* attributes for this memory descriptor entry.
* Notes:
* - If the cacheable attribute is set, the user can allocate
* memory that is backed by cache for better performance. It
* is not required that the memory be backed by cache.
* - If the physically contiguous attribute is set, then the
* entire memory must be physically contiguous across all
* page boundaries.
*/
u16 constant_memory_attributes;
};
/**
* sci_mdl_first_entry() - This method simply rewinds the MDL iterator back to
* the first memory descriptor entry in the list.
* @mdl: This parameter specifies the memory descriptor list that is to be
* rewound.
*
*/
void sci_mdl_first_entry(
struct sci_base_memory_descriptor_list *mdl);
/**
* sci_mdl_next_entry() - This method simply updates the "current" pointer to
* the next sequential memory descriptor.
* @mdl: This parameter specifies the memory descriptor list for which to
* return the next memory descriptor entry in the list.
*
* none.
*/
void sci_mdl_next_entry(
struct sci_base_memory_descriptor_list *mdl);
/**
* sci_mdl_get_current_entry() - This method simply returns the current memory
* descriptor entry.
* @mdl: This parameter specifies the memory descriptor list for which to
* return the current memory descriptor entry.
*
* This method returns a pointer to the current physical memory descriptor in
* the MDL. NULL This value is returned if there are no descriptors in the list.
*/
struct sci_physical_memory_descriptor *sci_mdl_get_current_entry(
struct sci_base_memory_descriptor_list *mdl);
#endif /* _SCI_MEMORY_DESCRIPTOR_LIST_H_ */

View File

@ -0,0 +1,99 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_OBJECT_H_
#define _SCI_OBJECT_H_
/**
* This file contains all of the method and constants associated with the SCI
* base object. The SCI base object is the class from which all other
* objects derive in the Storage Controller Interface.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
/**
* struct sci_base_object - all core objects must include this as their
* first member to permit the casting below
*
* TODO: unwind this assumption, convert these routines and callers to pass a struct
* sci_base_object pointer without casting, or convert 'private' to the
* expected type per-object
*
*/
struct sci_base_object {
void *private;
};
static inline void *sci_object_get_association(void *obj)
{
struct sci_base_object *base = obj;
return base->private;
}
static inline void sci_object_set_association(void *obj, void *private)
{
struct sci_base_object *base = obj;
base->private = private;
}
#endif /* _SCI_OBJECT_H_ */

View File

@ -0,0 +1,199 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the interface to the pool class. This class allows two
* different two different priority tasks to insert and remove items from
* the free pool. The user of the pool is expected to evaluate the pool
* condition empty before a get operation and pool condition full before a
* put operation. Methods Provided: - sci_pool_create() -
* sci_pool_initialize() - sci_pool_empty() - sci_pool_full() -
* sci_pool_get() - sci_pool_put()
*
*
*/
#ifndef _SCI_POOL_H_
#define _SCI_POOL_H_
/**
* SCI_POOL_INCREMENT() -
*
* Private operation for the pool
*/
#define SCI_POOL_INCREMENT(this_pool, index) \
(((index) + 1) == (this_pool).size ? 0 : (index) + 1)
/**
* SCI_POOL_CREATE() -
*
* This creates a pool structure of pool_name. The members in the pool are of
* type with number of elements equal to size.
*/
#define SCI_POOL_CREATE(pool_name, type, pool_size) \
struct \
{ \
u32 size; \
u32 get; \
u32 put; \
type array[(pool_size) + 1]; \
} pool_name
/**
* sci_pool_empty() -
*
* This macro evaluates the pool and returns true if the pool is empty. If the
* pool is empty the user should not perform any get operation on the pool.
*/
#define sci_pool_empty(this_pool) \
((this_pool).get == (this_pool).put)
/**
* sci_pool_full() -
*
* This macro evaluates the pool and returns true if the pool is full. If the
* pool is full the user should not perform any put operation.
*/
#define sci_pool_full(this_pool) \
(SCI_POOL_INCREMENT(this_pool, (this_pool).put) == (this_pool).get)
/**
* sci_pool_size() -
*
* This macro returns the size of the pool created. The internal size of the
* pool is actually 1 larger then necessary in order to ensure get and put
* pointers can be written simultaneously by different users. As a result,
* this macro subtracts 1 from the internal size
*/
#define sci_pool_size(this_pool) \
((this_pool).size - 1)
/**
* sci_pool_count() -
*
* This macro indicates the number of elements currently contained in the pool.
*/
#define sci_pool_count(this_pool) \
(\
sci_pool_empty((this_pool)) \
? 0 \
: (\
sci_pool_full((this_pool)) \
? sci_pool_size((this_pool)) \
: (\
(this_pool).get > (this_pool).put \
? ((this_pool).size - (this_pool).get + (this_pool).put) \
: ((this_pool).put - (this_pool).get) \
) \
) \
)
/**
* sci_pool_initialize() -
*
* This macro initializes the pool to an empty condition.
*/
#define sci_pool_initialize(this_pool) \
{ \
(this_pool).size = (sizeof((this_pool).array) / sizeof((this_pool).array[0])); \
(this_pool).get = 0; \
(this_pool).put = 0; \
}
/**
* sci_pool_get() -
*
* This macro will get the next free element from the pool. This should only be
* called if the pool is not empty.
*/
#define sci_pool_get(this_pool, my_value) \
{ \
(my_value) = (this_pool).array[(this_pool).get]; \
(this_pool).get = SCI_POOL_INCREMENT((this_pool), (this_pool).get); \
}
/**
* sci_pool_put() -
*
* This macro will put the value into the pool. This should only be called if
* the pool is not full.
*/
#define sci_pool_put(this_pool, the_value) \
{ \
(this_pool).array[(this_pool).put] = (the_value); \
(this_pool).put = SCI_POOL_INCREMENT((this_pool), (this_pool).put); \
}
/**
* sci_pool_erase() -
*
* This macro will search the pool and remove any elements in the pool matching
* the supplied value. This method can only be utilized on pools
*/
#define sci_pool_erase(this_pool, type, the_value) \
{ \
type tmp_value; \
u32 index; \
u32 element_count = sci_pool_count((this_pool)); \
\
for (index = 0; index < element_count; index++) { \
sci_pool_get((this_pool), tmp_value); \
if (tmp_value != (the_value)) \
sci_pool_put((this_pool), tmp_value); \
} \
}
#endif /* _SCI_POOL_H_ */

View File

@ -0,0 +1,409 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_STATUS_H_
#define _SCI_STATUS_H_
/**
* This file contains all of the return status codes utilized across the
* various sub-components in SCI.
*
*
*/
/**
* enum _SCI_STATUS - This is the general return status enumeration for non-IO,
* non-task management related SCI interface methods.
*
*
*/
enum sci_status {
/**
* This member indicates successful completion.
*/
SCI_SUCCESS = 0,
/**
* This value indicates that the calling method completed successfully,
* but that the IO may have completed before having it's start method
* invoked. This occurs during SAT translation for requests that do
* not require an IO to the target or for any other requests that may
* be completed without having to submit IO.
*/
SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
/**
* This Value indicates that the SCU hardware returned an early response
* because the io request specified more data than is returned by the
* target device (mode pages, inquiry data, etc.). The completion routine
* will handle this case to get the actual number of bytes transferred.
*/
SCI_SUCCESS_IO_DONE_EARLY,
/**
* This member indicates that the object for which a state change is
* being requested is already in said state.
*/
SCI_WARNING_ALREADY_IN_STATE,
/**
* This member indicates interrupt coalescence timer may cause SAS
* specification compliance issues (i.e. SMP target mode response
* frames must be returned within 1.9 milliseconds).
*/
SCI_WARNING_TIMER_CONFLICT,
/**
* This field indicates a sequence of action is not completed yet. Mostly,
* this status is used when multiple ATA commands are needed in a SATI translation.
*/
SCI_WARNING_SEQUENCE_INCOMPLETE,
/**
* This member indicates that there was a general failure.
*/
SCI_FAILURE,
/**
* This member indicates that the SCI implementation is unable to complete
* an operation due to a critical flaw the prevents any further operation
* (i.e. an invalid pointer).
*/
SCI_FATAL_ERROR,
/**
* This member indicates the calling function failed, because the state
* of the controller is in a state that prevents successful completion.
*/
SCI_FAILURE_INVALID_STATE,
/**
* This member indicates the calling function failed, because there is
* insufficient resources/memory to complete the request.
*/
SCI_FAILURE_INSUFFICIENT_RESOURCES,
/**
* This member indicates the calling function failed, because the
* controller object required for the operation can't be located.
*/
SCI_FAILURE_CONTROLLER_NOT_FOUND,
/**
* This member indicates the calling function failed, because the
* discovered controller type is not supported by the library.
*/
SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE,
/**
* This member indicates the calling function failed, because the
* requested initialization data version isn't supported.
*/
SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION,
/**
* This member indicates the calling function failed, because the
* requested configuration of SAS Phys into SAS Ports is not supported.
*/
SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION,
/**
* This member indicates the calling function failed, because the
* requested protocol is not supported by the remote device, port,
* or controller.
*/
SCI_FAILURE_UNSUPPORTED_PROTOCOL,
/**
* This member indicates the calling function failed, because the
* requested information type is not supported by the SCI implementation.
*/
SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE,
/**
* This member indicates the calling function failed, because the
* device already exists.
*/
SCI_FAILURE_DEVICE_EXISTS,
/**
* This member indicates the calling function failed, because adding
* a phy to the object is not possible.
*/
SCI_FAILURE_ADDING_PHY_UNSUPPORTED,
/**
* This member indicates the calling function failed, because the
* requested information type is not supported by the SCI implementation.
*/
SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD,
/**
* This member indicates the calling function failed, because the SCI
* implementation does not support the supplied time limit.
*/
SCI_FAILURE_UNSUPPORTED_TIME_LIMIT,
/**
* This member indicates the calling method failed, because the SCI
* implementation does not contain the specified Phy.
*/
SCI_FAILURE_INVALID_PHY,
/**
* This member indicates the calling method failed, because the SCI
* implementation does not contain the specified Port.
*/
SCI_FAILURE_INVALID_PORT,
/**
* This member indicates the calling method was partly successful
* The port was reset but not all phys in port are operational
*/
SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS,
/**
* This member indicates that calling method failed
* The port reset did not complete because none of the phys are operational
*/
SCI_FAILURE_RESET_PORT_FAILURE,
/**
* This member indicates the calling method failed, because the SCI
* implementation does not contain the specified remote device.
*/
SCI_FAILURE_INVALID_REMOTE_DEVICE,
/**
* This member indicates the calling method failed, because the remote
* device is in a bad state and requires a reset.
*/
SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
/**
* This member indicates the calling method failed, because the SCI
* implementation does not contain or support the specified IO tag.
*/
SCI_FAILURE_INVALID_IO_TAG,
/**
* This member indicates that the operation failed and the user should
* check the response data associated with the IO.
*/
SCI_FAILURE_IO_RESPONSE_VALID,
/**
* This member indicates that the operation failed, the failure is
* controller implementation specific, and the response data associated
* with the request is not valid. You can query for the controller
* specific error information via scic_controller_get_request_status()
*/
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
/**
* This member indicated that the operation failed because the
* user requested this IO to be terminated.
*/
SCI_FAILURE_IO_TERMINATED,
/**
* This member indicates that the operation failed and the associated
* request requires a SCSI abort task to be sent to the target.
*/
SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
/**
* This member indicates that the operation failed because the supplied
* device could not be located.
*/
SCI_FAILURE_DEVICE_NOT_FOUND,
/**
* This member indicates that the operation failed because the
* objects association is required and is not correctly set.
*/
SCI_FAILURE_INVALID_ASSOCIATION,
/**
* This member indicates that the operation failed, because a timeout
* occurred.
*/
SCI_FAILURE_TIMEOUT,
/**
* This member indicates that the operation failed, because the user
* specified a value that is either invalid or not supported.
*/
SCI_FAILURE_INVALID_PARAMETER_VALUE,
/**
* This value indicates that the operation failed, because the number
* of messages (MSI-X) is not supported.
*/
SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT,
/**
* This value indicates that the method failed due to a lack of
* available NCQ tags.
*/
SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
/**
* This value indicates that a protocol violation has occurred on the
* link.
*/
SCI_FAILURE_PROTOCOL_VIOLATION,
/**
* This value indicates a failure condition that retry may help to clear.
*/
SCI_FAILURE_RETRY_REQUIRED,
/**
* This field indicates the retry limit was reached when a retry is attempted
*/
SCI_FAILURE_RETRY_LIMIT_REACHED,
/**
* This member indicates the calling method was partly successful.
* Mostly, this status is used when a LUN_RESET issued to an expander attached
* STP device in READY NCQ substate needs to have RNC suspended/resumed
* before posting TC.
*/
SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS,
/**
* This field indicates an illegal phy connection based on the routing attribute
* of both expander phy attached to each other.
*/
SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION,
/**
* This field indicates a CONFIG ROUTE INFO command has a response with function result
* INDEX DOES NOT EXIST, usually means exceeding max route index.
*/
SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX,
/**
* This value indicates that an unsupported PCI device ID has been
* specified. This indicates that attempts to invoke
* scic_library_allocate_controller() will fail.
*/
SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID
};
/**
* enum _SCI_IO_STATUS - This enumeration depicts all of the possible IO
* completion status values. Each value in this enumeration maps directly
* to a value in the enum sci_status enumeration. Please refer to that
* enumeration for detailed comments concerning what the status represents.
*
* Add the API to retrieve the SCU status from the core. Check to see that the
* following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL
* - SCI_IO_FAILURE_INVALID_IO_TAG
*/
enum sci_io_status {
SCI_IO_SUCCESS = SCI_SUCCESS,
SCI_IO_FAILURE = SCI_FAILURE,
SCI_IO_SUCCESS_COMPLETE_BEFORE_START = SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
SCI_IO_SUCCESS_IO_DONE_EARLY = SCI_SUCCESS_IO_DONE_EARLY,
SCI_IO_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE,
SCI_IO_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES,
SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
SCI_IO_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID,
SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
SCI_IO_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED,
SCI_IO_FAILURE_REQUIRES_SCSI_ABORT = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
SCI_IO_FAILURE_PROTOCOL_VIOLATION = SCI_FAILURE_PROTOCOL_VIOLATION,
SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
SCI_IO_FAILURE_RETRY_REQUIRED = SCI_FAILURE_RETRY_REQUIRED,
SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED,
SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE
};
/**
* enum _SCI_TASK_STATUS - This enumeration depicts all of the possible task
* completion status values. Each value in this enumeration maps directly
* to a value in the enum sci_status enumeration. Please refer to that
* enumeration for detailed comments concerning what the status represents.
*
* Check to see that the following status are properly handled:
*/
enum sci_task_status {
SCI_TASK_SUCCESS = SCI_SUCCESS,
SCI_TASK_FAILURE = SCI_FAILURE,
SCI_TASK_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE,
SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES,
SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
SCI_TASK_FAILURE_INVALID_TAG = SCI_FAILURE_INVALID_IO_TAG,
SCI_TASK_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID,
SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
SCI_TASK_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED,
SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS
};
#endif /* _SCI_STATUS_H_ */

View File

@ -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.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_TYPES_H_
#define _SCI_TYPES_H_
#include <linux/string.h>
#define sci_cb_make_physical_address(physical_addr, addr_upper, addr_lower) \
((physical_addr) = (addr_lower) | ((u64)addr_upper) << 32)
#define SCI_INVALID_HANDLE 0x0
/**
* The SCI_LIBRARY_HANDLE_T will be utilized by SCI users as an opaque handle
* for the SCI Library object.
*
* SCI_LIBRARY_HANDLE_T
*/
typedef void *SCI_LIBRARY_HANDLE_T;
typedef enum {
SCI_IO_REQUEST_DATA_IN = 0, /* Read operation */
SCI_IO_REQUEST_DATA_OUT, /* Write operation */
SCI_IO_REQUEST_NO_DATA
} SCI_IO_REQUEST_DATA_DIRECTION;
enum sci_controller_mode {
SCI_MODE_SPEED, /* Optimized for performance */
SCI_MODE_SIZE /* Optimized for memory use */
};
#endif /* _SCI_TYPES_H_ */

View File

@ -0,0 +1,70 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "sci_util.h"
void scic_word_copy_with_swap(
u32 *destination,
u32 *source,
u32 word_count)
{
while (word_count--) {
*destination = SCIC_SWAP_DWORD(*source);
source++;
destination++;
}
}

View File

@ -0,0 +1,138 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_UTIL_H_
#define _SCI_UTIL_H_
#include "sci_types.h"
/**
* SCIC_SWAP_DWORD() -
*
* Normal byte swap macro
*/
#define SCIC_SWAP_DWORD(x) \
(\
(((x) >> 24) & 0x000000FF) \
| (((x) >> 8) & 0x0000FF00) \
| (((x) << 8) & 0x00FF0000) \
| (((x) << 24) & 0xFF000000) \
)
#define SCIC_BUILD_DWORD(char_buffer) \
(\
((char_buffer)[0] << 24) \
| ((char_buffer)[1] << 16) \
| ((char_buffer)[2] << 8) \
| ((char_buffer)[3]) \
)
#define SCI_FIELD_OFFSET(type, field) ((unsigned long)&(((type *)0)->field))
/**
* sci_physical_address_add() -
*
* This macro simply performs addition on an dma_addr_t type. The
* lower u32 value is "clipped" or "wrapped" back through 0. When this occurs
* the upper 32-bits are incremented by 1.
*/
#define sci_physical_address_add(physical_address, value) \
{ \
u32 lower = lower_32_bits((physical_address)); \
u32 upper = upper_32_bits((physical_address)); \
\
if (lower + (value) < lower) \
upper += 1; \
\
lower += (value); \
sci_cb_make_physical_address(physical_address, upper, lower); \
}
/**
* sci_physical_address_subtract() -
*
* This macro simply performs subtraction on an dma_addr_t type. The
* lower u32 value is "clipped" or "wrapped" back through 0. When this occurs
* the upper 32-bits are decremented by 1.
*/
#define sci_physical_address_subtract(physical_address, value) \
{ \
u32 lower = lower_32_bits((physical_address)); \
u32 upper = upper_32_bits((physical_address)); \
\
if (lower - (value) > lower) \
upper -= 1; \
\
lower -= (value); \
sci_cb_make_physical_address(physical_address, upper, lower); \
}
/**
* scic_word_copy_with_swap() - Copy the data from source to destination and
* swap the bytes during the copy.
* @destination: This parameter specifies the destination address to which the
* data is to be copied.
* @source: This parameter specifies the source address from which data is to
* be copied.
* @word_count: This parameter specifies the number of 32-bit words to copy and
* byte swap.
*
*/
void scic_word_copy_with_swap(
u32 *destination,
u32 *source,
u32 word_count);
#endif /* _SCI_UTIL_H_ */

View File

@ -0,0 +1,347 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_USER_PARAMETERS_H_
#define _SCIC_SDS_USER_PARAMETERS_H_
/**
* This file contains all of the structure definitions and interface methods
* that can be called by a SCIC user on the SCU Driver Standard
* (struct scic_sds_user_parameters) user parameter block.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
#include "intel_sas.h"
#include "sci_controller_constants.h"
struct scic_sds_controller;
/**
*
*
* SCIC_SDS_PARM_PHY_SPEED These constants define the speeds utilized for a
* phy/port.
*/
#define SCIC_SDS_PARM_NO_SPEED 0
/**
*
*
* This value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
*/
#define SCIC_SDS_PARM_GEN1_SPEED 1
/**
*
*
* This value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
*/
#define SCIC_SDS_PARM_GEN2_SPEED 2
/**
*
*
* This value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
*/
#define SCIC_SDS_PARM_GEN3_SPEED 3
/**
*
*
* For range checks, the max speed generation
*/
#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED
/**
* struct scic_sds_user_parameters - This structure delineates the various user
* parameters that can be changed by the core user.
*
*
*/
struct scic_sds_user_parameters {
struct {
/**
* This field specifies the NOTIFY (ENABLE SPIN UP) primitive
* insertion frequency for this phy index.
*/
u32 notify_enable_spin_up_insertion_frequency;
/**
* This method specifies the number of transmitted DWORDs within which
* to transmit a single ALIGN primitive. This value applies regardless
* of what type of device is attached or connection state. A value of
* 0 indicates that no ALIGN primitives will be inserted.
*/
u16 align_insertion_frequency;
/**
* This method specifies the number of transmitted DWORDs within which
* to transmit 2 ALIGN primitives. This applies for SAS connections
* only. A minimum value of 3 is required for this field.
*/
u16 in_connection_align_insertion_frequency;
/**
* This field indicates the maximum speed generation to be utilized
* by phys in the supplied port.
* - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
* - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
* - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
*/
u8 max_speed_generation;
} phys[SCI_MAX_PHYS];
/**
* This field specifies the maximum number of direct attached devices
* that can have power supplied to them simultaneously.
*/
u8 max_number_concurrent_device_spin_up;
/**
* This field specifies the number of seconds to allow a phy to consume
* power before yielding to another phy.
*
*/
u8 phy_spin_up_delay_interval;
/**
* These timer values specifies how long a link will remain open with no
* activity in increments of a microsecond, it can be in increments of
* 100 microseconds if the upper most bit is set.
*
*/
u16 stp_inactivity_timeout;
u16 ssp_inactivity_timeout;
/**
* These timer values specifies how long a link will remain open in increments
* of 100 microseconds.
*
*/
u16 stp_max_occupancy_timeout;
u16 ssp_max_occupancy_timeout;
/**
* This timer value specifies how long a link will remain open with no
* outbound traffic in increments of a microsecond.
*
*/
u8 no_outbound_task_timeout;
};
/**
* This structure/union specifies the various different user parameter sets
* available. Each type is specific to a hardware controller version.
*
* union scic_user_parameters
*/
union scic_user_parameters {
/**
* This field specifies the user parameters specific to the
* Storage Controller Unit (SCU) Driver Standard (SDS) version
* 1.
*/
struct scic_sds_user_parameters sds1;
};
/**
*
*
* SCIC_SDS_OEM_PHY_MASK These constants define the valid values for phy_mask
*/
/**
*
*
* This is the min value assignable to a port's phy mask
*/
#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0
/**
*
*
* This is the max value assignable to a port's phy mask
*/
#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF
/**
* struct scic_sds_oem_parameters - This structure delineates the various OEM
* parameters that must be set the core user.
*
*
*/
struct scic_sds_oem_parameters {
struct {
/**
* This field indicates whether Spread Spectrum Clocking (SSC)
* should be enabled or disabled.
*/
bool do_enable_ssc;
} controller;
struct {
/**
* This field specifies the phys to be contained inside a port.
* The bit position in the mask specifies the index of the phy
* to be contained in the port. Multiple bits (i.e. phys)
* can be contained in a single port.
*/
u8 phy_mask;
} ports[SCI_MAX_PORTS];
struct {
/**
* This field specifies the SAS address to be transmitted on
* for this phy index.
*/
struct sci_sas_address sas_address;
} phys[SCI_MAX_PHYS];
};
/**
* This structure/union specifies the various different OEM parameter sets
* available. Each type is specific to a hardware controller version.
*
* union scic_oem_parameters
*/
union scic_oem_parameters {
/**
* This field specifies the OEM parameters specific to the
* Storage Controller Unit (SCU) Driver Standard (SDS) version
* 1.
*/
struct scic_sds_oem_parameters sds1;
};
/**
* scic_user_parameters_set() - This method allows the user to attempt to
* change the user parameters utilized by the controller.
* @controller: This parameter specifies the controller on which to set the
* user parameters.
* @user_parameters: This parameter specifies the USER_PARAMETERS object
* containing the potential new values.
*
* Indicate if the update of the user parameters was successful. SCI_SUCCESS
* This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE
* This value is returned if the attempt to change the user parameter failed,
* because changing one of the parameters is not currently allowed.
* SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user
* supplied an invalid interrupt coalescence time, spin up delay interval, etc.
*/
enum sci_status scic_user_parameters_set(
struct scic_sds_controller *controller,
union scic_user_parameters *user_parameters);
/**
* scic_user_parameters_get() - This method allows the user to retrieve the
* user parameters utilized by the controller.
* @controller: This parameter specifies the controller on which to set the
* user parameters.
* @user_parameters: This parameter specifies the USER_PARAMETERS object into
* which the framework shall save it's parameters.
*
*/
void scic_user_parameters_get(
struct scic_sds_controller *controller,
union scic_user_parameters *user_parameters);
/**
* scic_oem_parameters_set() - This method allows the user to attempt to change
* the OEM parameters utilized by the controller.
* @controller: This parameter specifies the controller on which to set the
* user parameters.
* @oem_parameters: This parameter specifies the OEM parameters object
* containing the potential new values.
*
* Indicate if the update of the user parameters was successful. SCI_SUCCESS
* This value is returned if the operation succeeded. SCI_FAILURE_INVALID_STATE
* This value is returned if the attempt to change the user parameter failed,
* because changing one of the parameters is not currently allowed.
* SCI_FAILURE_INVALID_PARAMETER_VALUE This value is returned if the user
* supplied an unsupported value for one of the OEM parameters.
*/
enum sci_status scic_oem_parameters_set(
struct scic_sds_controller *controller,
union scic_oem_parameters *oem_parameters);
/**
* scic_oem_parameters_get() - This method allows the user to retreive the OEM
* parameters utilized by the controller.
* @controller: This parameter specifies the controller on which to set the
* user parameters.
* @oem_parameters: This parameter specifies the OEM parameters object in which
* to write the core's OEM parameters.
*
*/
void scic_oem_parameters_get(
struct scic_sds_controller *controller,
union scic_oem_parameters *oem_parameters);
#endif /* _SCIC_SDS_USER_PARAMETERS_H_ */

View File

@ -0,0 +1,586 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_CONTROLLER_H_
#define _SCIC_CONTROLLER_H_
/**
* This file contains all of the interface methods that can be called by an
* SCIC user on a controller object.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
#include "sci_controller.h"
#include "scic_config_parameters.h"
struct scic_sds_request;
struct scic_sds_phy;
struct scic_sds_port;
struct scic_sds_remote_device;
/**
* enum _SCIC_INTERRUPT_TYPE - This enumeration depicts the various types of
* interrupts that are potentially supported by a SCI Core implementation.
*
*
*/
enum scic_interrupt_type {
SCIC_LEGACY_LINE_INTERRUPT_TYPE,
SCIC_MSIX_INTERRUPT_TYPE,
/**
* This enumeration value indicates the use of polling.
*/
SCIC_NO_INTERRUPTS
};
/**
* This method is called by the SCI user in order to have the SCI
* implementation handle the interrupt. This method performs minimal
* processing to allow for streamlined interrupt time usage.
*
* SCIC_CONTROLLER_INTERRUPT_HANDLER true: returned if there is an interrupt to
* process and it was processed. false: returned if no interrupt was processed.
*/
typedef bool (*SCIC_CONTROLLER_INTERRUPT_HANDLER)(
struct scic_sds_controller *controller
);
/**
* This method is called by the SCI user to process completions generated as a
* result of a previously handled interrupt. This method will result in the
* completion of IO requests and handling of other controller generated
* events. This method should be called some time after the interrupt
* handler.
*
* Most, if not all, of the user callback APIs are invoked from within this
* API. As a result, the user should be cognizent of the operating level at
* which they invoke this API.
*/
typedef void (*SCIC_CONTROLLER_COMPLETION_HANDLER)(
struct scic_sds_controller *controller
);
/**
* struct scic_controller_handler_methods - This structure contains an
* interrupt handler and completion handler function pointers.
*
*
*/
struct scic_controller_handler_methods {
SCIC_CONTROLLER_INTERRUPT_HANDLER interrupt_handler;
SCIC_CONTROLLER_COMPLETION_HANDLER completion_handler;
};
/**
* scic_controller_construct() - This method will attempt to construct a
* controller object utilizing the supplied parameter information.
* @c: This parameter specifies the controller to be constructed.
* @scu_base: mapped base address of the scu registers
* @smu_base: mapped base address of the smu registers
*
* Indicate if the controller was successfully constructed or if it failed in
* some way. SCI_SUCCESS This value is returned if the controller was
* successfully constructed. SCI_WARNING_TIMER_CONFLICT This value is returned
* if the interrupt coalescence timer may cause SAS compliance issues for SMP
* Target mode response processing. SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE
* This value is returned if the controller does not support the supplied type.
* SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION This value is returned if the
* controller does not support the supplied initialization data version.
*/
enum sci_status scic_controller_construct(struct scic_sds_controller *c,
void __iomem *scu_base,
void __iomem *smu_base);
/**
* scic_controller_enable_interrupts() - This method will enable all controller
* interrupts.
* @controller: This parameter specifies the controller for which to enable
* interrupts.
*
*/
void scic_controller_enable_interrupts(
struct scic_sds_controller *controller);
/**
* scic_controller_disable_interrupts() - This method will disable all
* controller interrupts.
* @controller: This parameter specifies the controller for which to disable
* interrupts.
*
*/
void scic_controller_disable_interrupts(
struct scic_sds_controller *controller);
/**
* scic_controller_get_handler_methods() - This method will return provide
* function pointers for the interrupt handler and completion handler. The
* interrupt handler is expected to be invoked at interrupt time. The
* completion handler is scheduled to run as a result of the interrupt
* handler. The completion handler performs the bulk work for processing
* silicon events.
* @interrupt_type: This parameter informs the core which type of
* interrupt/completion methods are being requested. These are the types:
* SCIC_LEGACY_LINE_INTERRUPT_TYPE, SCIC_MSIX_INTERRUPT_TYPE,
* SCIC_NO_INTERRUPTS (POLLING)
* @message_count: This parameter informs the core the number of MSI-X messages
* to be utilized. This parameter must be 0 when requesting legacy line
* based handlers.
* @handler_methods: The caller provides a pointer to a buffer of type
* struct scic_controller_handler_methods. The size depends on the combination of
* the interrupt_type and message_count input parameters:
* SCIC_LEGACY_LINE_INTERRUPT_TYPE: - size =
* sizeof(struct scic_controller_handler_methods) SCIC_MSIX_INTERRUPT_TYPE:
* sizeof(struct scic_controller_handler_methods)
* @handler_methods: SCIC fills out the caller's buffer with the appropriate
* interrupt and completion handlers based on the info provided in the
* interrupt_type and message_count input parameters. For
* SCIC_LEGACY_LINE_INTERRUPT_TYPE, the buffer receives a single
* struct scic_controller_handler_methods element regardless that the
* message_count parameter is zero. For SCIC_MSIX_INTERRUPT_TYPE, the buffer
* receives an array of elements of type struct scic_controller_handler_methods
* where the array size is equivalent to the message_count parameter. The
* array is zero-relative where entry zero corresponds to message-vector
* zero, entry one corresponds to message-vector one, and so forth.
*
* Indicate if the handler retrieval operation was successful. SCI_SUCCESS This
* value is returned if retrieval succeeded.
* SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT This value is returned if the user
* supplied an unsupported number of MSI-X messages. For legacy line interrupts
* the only valid value is 0.
*/
enum sci_status scic_controller_get_handler_methods(
enum scic_interrupt_type interrupt_type,
u16 message_count,
struct scic_controller_handler_methods *handler_methods);
/**
* scic_controller_initialize() - This method will initialize the controller
* hardware managed by the supplied core controller object. This method
* will bring the physical controller hardware out of reset and enable the
* core to determine the capabilities of the hardware being managed. Thus,
* the core controller can determine it's exact physical (DMA capable)
* memory requirements.
* @controller: This parameter specifies the controller to be initialized.
*
* The SCI Core user must have called scic_controller_construct() on the
* supplied controller object previously. Indicate if the controller was
* successfully initialized or if it failed in some way. SCI_SUCCESS This value
* is returned if the controller hardware was successfully initialized.
*/
enum sci_status scic_controller_initialize(
struct scic_sds_controller *controller);
/**
* scic_controller_get_suggested_start_timeout() - This method returns the
* suggested scic_controller_start() timeout amount. The user is free to
* use any timeout value, but this method provides the suggested minimum
* start timeout value. The returned value is based upon empirical
* information determined as a result of interoperability testing.
* @controller: the handle to the controller object for which to return the
* suggested start timeout.
*
* This method returns the number of milliseconds for the suggested start
* operation timeout.
*/
u32 scic_controller_get_suggested_start_timeout(
struct scic_sds_controller *controller);
/**
* scic_controller_start() - This method will start the supplied core
* controller. This method will start the staggered spin up operation. The
* SCI User completion callback is called when the following conditions are
* met: -# the return status of this method is SCI_SUCCESS. -# after all of
* the phys have successfully started or been given the opportunity to start.
* @controller: the handle to the controller object to start.
* @timeout: This parameter specifies the number of milliseconds in which the
* start operation should complete.
*
* The SCI Core user must have filled in the physical memory descriptor
* structure via the sci_controller_get_memory_descriptor_list() method. The
* SCI Core user must have invoked the scic_controller_initialize() method
* prior to invoking this method. The controller must be in the INITIALIZED or
* STARTED state. Indicate if the controller start method succeeded or failed
* in some way. SCI_SUCCESS if the start operation succeeded.
* SCI_WARNING_ALREADY_IN_STATE if the controller is already in the STARTED
* state. SCI_FAILURE_INVALID_STATE if the controller is not either in the
* INITIALIZED or STARTED states. SCI_FAILURE_INVALID_MEMORY_DESCRIPTOR if
* there are inconsistent or invalid values in the supplied
* struct sci_physical_memory_descriptor array.
*/
enum sci_status scic_controller_start(
struct scic_sds_controller *controller,
u32 timeout);
/**
* scic_controller_stop() - This method will stop an individual controller
* object.This method will invoke the associated user callback upon
* completion. The completion callback is called when the following
* conditions are met: -# the method return status is SCI_SUCCESS. -# the
* controller has been quiesced. This method will ensure that all IO
* requests are quiesced, phys are stopped, and all additional operation by
* the hardware is halted.
* @controller: the handle to the controller object to stop.
* @timeout: This parameter specifies the number of milliseconds in which the
* stop operation should complete.
*
* The controller must be in the STARTED or STOPPED state. Indicate if the
* controller stop method succeeded or failed in some way. SCI_SUCCESS if the
* stop operation successfully began. SCI_WARNING_ALREADY_IN_STATE if the
* controller is already in the STOPPED state. SCI_FAILURE_INVALID_STATE if the
* controller is not either in the STARTED or STOPPED states.
*/
enum sci_status scic_controller_stop(
struct scic_sds_controller *controller,
u32 timeout);
/**
* scic_controller_reset() - This method will reset the supplied core
* controller regardless of the state of said controller. This operation is
* considered destructive. In other words, all current operations are wiped
* out. No IO completions for outstanding devices occur. Outstanding IO
* requests are not aborted or completed at the actual remote device.
* @controller: the handle to the controller object to reset.
*
* Indicate if the controller reset method succeeded or failed in some way.
* SCI_SUCCESS if the reset operation successfully started. SCI_FATAL_ERROR if
* the controller reset operation is unable to complete.
*/
enum sci_status scic_controller_reset(
struct scic_sds_controller *controller);
/**
* scic_controller_start_io() - This method is called by the SCI user to
* send/start an IO request. If the method invocation is successful, then
* the IO request has been queued to the hardware for processing.
* @controller: the handle to the controller object for which to start an IO
* request.
* @remote_device: the handle to the remote device object for which to start an
* IO request.
* @io_request: the handle to the io request object to start.
* @io_tag: This parameter specifies a previously allocated IO tag that the
* user desires to be utilized for this request. This parameter is optional.
* The user is allowed to supply SCI_CONTROLLER_INVALID_IO_TAG as the value
* for this parameter.
*
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
* to ensure that each of the methods that may allocate or free available IO
* tags are handled in a mutually exclusive manner. This method is one of said
* methods requiring proper critical code section protection (e.g. semaphore,
* spin-lock, etc.). - For SATA, the user is required to manage NCQ tags. As a
* result, it is expected the user will have set the NCQ tag field in the host
* to device register FIS prior to calling this method. There is also a
* requirement for the user to call scic_stp_io_set_ncq_tag() prior to invoking
* the scic_controller_start_io() method. scic_controller_allocate_tag() for
* more information on allocating a tag. Indicate if the controller
* successfully started the IO request. SCI_IO_SUCCESS if the IO request was
* successfully started. Determine the failure situations and return values.
*/
enum sci_io_status scic_controller_start_io(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *io_request,
u16 io_tag);
/**
* scic_controller_start_task() - This method is called by the SCIC user to
* send/start a framework task management request.
* @controller: the handle to the controller object for which to start the task
* management request.
* @remote_device: the handle to the remote device object for which to start
* the task management request.
* @task_request: the handle to the task request object to start.
* @io_tag: This parameter specifies a previously allocated IO tag that the
* user desires to be utilized for this request. Note this not the io_tag
* of the request being managed. It is to be utilized for the task request
* itself. This parameter is optional. The user is allowed to supply
* SCI_CONTROLLER_INVALID_IO_TAG as the value for this parameter.
*
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
* to ensure that each of the methods that may allocate or free available IO
* tags are handled in a mutually exclusive manner. This method is one of said
* methods requiring proper critical code section protection (e.g. semaphore,
* spin-lock, etc.). - The user must synchronize this task with completion
* queue processing. If they are not synchronized then it is possible for the
* io requests that are being managed by the task request can complete before
* starting the task request. scic_controller_allocate_tag() for more
* information on allocating a tag. Indicate if the controller successfully
* started the IO request. SCI_TASK_SUCCESS if the task request was
* successfully started. SCI_TASK_FAILURE_REQUIRES_SCSI_ABORT This value is
* returned if there is/are task(s) outstanding that require termination or
* completion before this request can succeed.
*/
enum sci_task_status scic_controller_start_task(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *task_request,
u16 io_tag);
/**
* scic_controller_complete_task() - This method will perform core specific
* completion operations for task management request. After this method is
* invoked, the user should consider the task request as invalid until it is
* properly reused (i.e. re-constructed).
* @controller: The handle to the controller object for which to complete the
* task management request.
* @remote_device: The handle to the remote device object for which to complete
* the task management request.
* @task_request: the handle to the task management request object to complete.
*
* Indicate if the controller successfully completed the task management
* request. SCI_SUCCESS if the completion process was successful.
*/
enum sci_status scic_controller_complete_task(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *task_request);
/**
* scic_controller_terminate_request() - This method is called by the SCI Core
* user to terminate an ongoing (i.e. started) core IO request. This does
* not abort the IO request at the target, but rather removes the IO request
* from the host controller.
* @controller: the handle to the controller object for which to terminate a
* request.
* @remote_device: the handle to the remote device object for which to
* terminate a request.
* @request: the handle to the io or task management request object to
* terminate.
*
* Indicate if the controller successfully began the terminate process for the
* IO request. SCI_SUCCESS if the terminate process was successfully started
* for the request. Determine the failure situations and return values.
*/
enum sci_status scic_controller_terminate_request(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *request);
/**
* scic_controller_complete_io() - This method will perform core specific
* completion operations for an IO request. After this method is invoked,
* the user should consider the IO request as invalid until it is properly
* reused (i.e. re-constructed).
* @controller: The handle to the controller object for which to complete the
* IO request.
* @remote_device: The handle to the remote device object for which to complete
* the IO request.
* @io_request: the handle to the io request object to complete.
*
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
* to ensure that each of the methods that may allocate or free available IO
* tags are handled in a mutually exclusive manner. This method is one of said
* methods requiring proper critical code section protection (e.g. semaphore,
* spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI
* Core user, using the scic_controller_allocate_io_tag() method, then it is
* the responsibility of the caller to invoke the scic_controller_free_io_tag()
* method to free the tag (i.e. this method will not free the IO tag). Indicate
* if the controller successfully completed the IO request. SCI_SUCCESS if the
* completion process was successful.
*/
enum sci_status scic_controller_complete_io(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *io_request);
/**
* scic_controller_get_port_handle() - This method simply provides the user
* with a unique handle for a given SAS/SATA core port index.
* @controller: This parameter represents the handle to the controller object
* from which to retrieve a port (SAS or SATA) handle.
* @port_index: This parameter specifies the port index in the controller for
* which to retrieve the port handle. 0 <= port_index < maximum number of
* phys.
* @port_handle: This parameter specifies the retrieved port handle to be
* provided to the caller.
*
* Indicate if the retrieval of the port handle was successful. SCI_SUCCESS
* This value is returned if the retrieval was successful.
* SCI_FAILURE_INVALID_PORT This value is returned if the supplied port id is
* not in the supported range.
*/
enum sci_status scic_controller_get_port_handle(
struct scic_sds_controller *controller,
u8 port_index,
struct scic_sds_port **port_handle);
/**
* scic_controller_get_phy_handle() - This method simply provides the user with
* a unique handle for a given SAS/SATA phy index/identifier.
* @controller: This parameter represents the handle to the controller object
* from which to retrieve a phy (SAS or SATA) handle.
* @phy_index: This parameter specifies the phy index in the controller for
* which to retrieve the phy handle. 0 <= phy_index < maximum number of phys.
* @phy_handle: This parameter specifies the retrieved phy handle to be
* provided to the caller.
*
* Indicate if the retrieval of the phy handle was successful. SCI_SUCCESS This
* value is returned if the retrieval was successful. SCI_FAILURE_INVALID_PHY
* This value is returned if the supplied phy id is not in the supported range.
*/
enum sci_status scic_controller_get_phy_handle(
struct scic_sds_controller *controller,
u8 phy_index,
struct scic_sds_phy **phy_handle);
/**
* scic_controller_allocate_io_tag() - This method will allocate a tag from the
* pool of free IO tags. Direct allocation of IO tags by the SCI Core user
* is optional. The scic_controller_start_io() method will allocate an IO
* tag if this method is not utilized and the tag is not supplied to the IO
* construct routine. Direct allocation of IO tags may provide additional
* performance improvements in environments capable of supporting this usage
* model. Additionally, direct allocation of IO tags also provides
* additional flexibility to the SCI Core user. Specifically, the user may
* retain IO tags across the lives of multiple IO requests.
* @controller: the handle to the controller object for which to allocate the
* tag.
*
* IO tags are a protected resource. It is incumbent upon the SCI Core user to
* ensure that each of the methods that may allocate or free available IO tags
* are handled in a mutually exclusive manner. This method is one of said
* methods requiring proper critical code section protection (e.g. semaphore,
* spin-lock, etc.). An unsigned integer representing an available IO tag.
* SCI_CONTROLLER_INVALID_IO_TAG This value is returned if there are no
* currently available tags to be allocated. All return other values indicate a
* legitimate tag.
*/
u16 scic_controller_allocate_io_tag(
struct scic_sds_controller *controller);
/**
* scic_controller_free_io_tag() - This method will free an IO tag to the pool
* of free IO tags. This method provides the SCI Core user more flexibility
* with regards to IO tags. The user may desire to keep an IO tag after an
* IO request has completed, because they plan on re-using the tag for a
* subsequent IO request. This method is only legal if the tag was
* allocated via scic_controller_allocate_io_tag().
* @controller: This parameter specifies the handle to the controller object
* for which to free/return the tag.
* @io_tag: This parameter represents the tag to be freed to the pool of
* available tags.
*
* - IO tags are a protected resource. It is incumbent upon the SCI Core user
* to ensure that each of the methods that may allocate or free available IO
* tags are handled in a mutually exclusive manner. This method is one of said
* methods requiring proper critical code section protection (e.g. semaphore,
* spin-lock, etc.). - If the IO tag for a request was allocated, by the SCI
* Core user, using the scic_controller_allocate_io_tag() method, then it is
* the responsibility of the caller to invoke this method to free the tag. This
* method returns an indication of whether the tag was successfully put back
* (freed) to the pool of available tags. SCI_SUCCESS This return value
* indicates the tag was successfully placed into the pool of available IO
* tags. SCI_FAILURE_INVALID_IO_TAG This value is returned if the supplied tag
* is not a valid IO tag value.
*/
enum sci_status scic_controller_free_io_tag(
struct scic_sds_controller *controller,
u16 io_tag);
/**
* scic_controller_set_mode() - This method allows the user to configure the
* SCI core into either a performance mode or a memory savings mode.
* @controller: This parameter represents the handle to the controller object
* for which to update the operating mode.
* @mode: This parameter specifies the new mode for the controller.
*
* Indicate if the user successfully change the operating mode of the
* controller. SCI_SUCCESS The user successfully updated the mode.
*/
enum sci_status scic_controller_set_mode(
struct scic_sds_controller *controller,
enum sci_controller_mode mode);
/**
* scic_controller_set_interrupt_coalescence() - This method allows the user to
* configure the interrupt coalescence.
* @controller: This parameter represents the handle to the controller object
* for which its interrupt coalesce register is overridden.
* @coalesce_number: Used to control the number of entries in the Completion
* Queue before an interrupt is generated. If the number of entries exceed
* this number, an interrupt will be generated. The valid range of the input
* is [0, 256]. A setting of 0 results in coalescing being disabled.
* @coalesce_timeout: Timeout value in microseconds. The valid range of the
* input is [0, 2700000] . A setting of 0 is allowed and results in no
* interrupt coalescing timeout.
*
* Indicate if the user successfully set the interrupt coalesce parameters.
* SCI_SUCCESS The user successfully updated the interrutp coalescence.
* SCI_FAILURE_INVALID_PARAMETER_VALUE The user input value is out of range.
*/
enum sci_status scic_controller_set_interrupt_coalescence(
struct scic_sds_controller *controller,
u32 coalesce_number,
u32 coalesce_timeout);
struct device;
struct scic_sds_controller *scic_controller_alloc(struct device *dev);
#endif /* _SCIC_CONTROLLER_H_ */

View File

@ -0,0 +1,512 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_IO_REQUEST_H_
#define _SCIC_IO_REQUEST_H_
/**
* This file contains the structures and interface methods that can be
* referenced and used by the SCI user for the SCI IO request object.
*
* Determine the failure situations and return values.
*/
#include "sci_types.h"
#include "sci_status.h"
#include "intel_sas.h"
struct scic_sds_request;
struct scic_sds_remote_device;
struct scic_sds_controller;
/**
* struct scic_io_parameters - This structure contains additional optional
* parameters for SSP IO requests. These parameters are utilized with the
* scic_io_request_construct_advanced_ssp() method.
*
* Add Block-guard/DIF, TLR
*/
struct scic_io_parameters {
/**
* This sub-structure contains SCSI specific features (for use with SSP
* IO requests).
*/
struct {
/**
* Data Integrity Format (DIF) is also known as protection information
* or block-guard. This sub-structure contains DIF specific feature
* information for SSP IO requests.
*/
struct {
void *placeholder;
} dif;
/**
* Transport Layer Retries (TLR) is an SSP protocol specific feature.
* This sub-structure contains Transport Layer Retries (TLR) specific
* feature information for SSP IO requests.
*/
struct {
void *placeholder;
} tlr;
} scsi;
};
/**
* struct scic_passthru_request_callbacks - This structure contains the pointer
* to the callback functions for constructing the passthrough request common
* to SSP, SMP and STP. This structure must be set by the win sci layer
* before the passthrough build is called
*
*
*/
struct scic_passthru_request_callbacks {
/**
* Function pointer to get the phy identifier for passthrough request.
*/
u32 (*scic_cb_passthru_get_phy_identifier)(void *, u8 *);
/**
* Function pointer to get the port identifier for passthrough request.
*/
u32 (*scic_cb_passthru_get_port_identifier)(void *, u8 *);
/**
* Function pointer to get the connection rate for passthrough request.
*/
u32 (*scic_cb_passthru_get_connection_rate)(void *, void *);
/**
* Function pointer to get the destination sas address for passthrough request.
*/
void (*scic_cb_passthru_get_destination_sas_address)(void *, u8 **);
/**
* Function pointer to get the transfer length for passthrough request.
*/
u32 (*scic_cb_passthru_get_transfer_length)(void *);
/**
* Function pointer to get the data direction for passthrough request.
*/
u32 (*scic_cb_passthru_get_data_direction)(void *);
};
/**
* struct scic_ssp_passthru_request_callbacks - This structure contains the
* pointer to the callback functions for constructing the passthrough
* request specific to SSP. This structure must be set by the win sci layer
* before the passthrough build is called
*
*
*/
struct scic_ssp_passthru_request_callbacks {
/**
* Common callbacks for all Passthru requests
*/
struct scic_passthru_request_callbacks common_callbacks;
/**
* Function pointer to get the lun for passthrough request.
*/
void (*scic_cb_ssp_passthru_get_lun)(void *, u8 **);
/**
* Function pointer to get the cdb
*/
void (*scic_cb_ssp_passthru_get_cdb)(void *, u32 *, u8 **, u32 *, u8 **);
/**
* Function pointer to get the task attribute for passthrough request.
*/
u32 (*scic_cb_ssp_passthru_get_task_attribute)(void *);
};
/**
* struct scic_stp_passthru_request_callbacks - This structure contains the
* pointer to the callback functions for constructing the passthrough
* request specific to STP. This structure must be set by the win sci layer
* before the passthrough build is called
*
*
*/
struct scic_stp_passthru_request_callbacks {
/**
* Common callbacks for all Passthru requests
*/
struct scic_passthru_request_callbacks common_callbacks;
/**
* Function pointer to get the protocol for passthrough request.
*/
u8 (*scic_cb_stp_passthru_get_protocol)(void *);
/**
* Function pointer to get the resgister fis
*/
void (*scic_cb_stp_passthru_get_register_fis)(void *, u8 **);
/**
* Function pointer to get the MULTIPLE_COUNT (bits 5,6,7 in Byte 1 in the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
*/
u8 (*scic_cb_stp_passthru_get_multiplecount)(void *);
/**
* Function pointer to get the EXTEND (bit 0 in Byte 1 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
*/
u8 (*scic_cb_stp_passthru_get_extend)(void *);
/**
* Function pointer to get the CK_COND (bit 5 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
*/
u8 (*scic_cb_stp_passthru_get_ckcond)(void *);
/**
* Function pointer to get the T_DIR (bit 3 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
*/
u8 (*scic_cb_stp_passthru_get_tdir)(void *);
/**
* Function pointer to get the BYTE_BLOCK (bit 2 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
*/
u8 (*scic_cb_stp_passthru_get_byteblock)(void *);
/**
* Function pointer to get the T_LENGTH (bits 0,1 in Byte 2 the SAT-specific SCSI extenstion in ATA Pass-through (0x85))
*/
u8 (*scic_cb_stp_passthru_get_tlength)(void *);
};
/**
* struct scic_smp_passthru_request_callbacks - This structure contains the
* pointer to the callback functions for constructing the passthrough
* request specific to SMP. This structure must be set by the win sci layer
* before the passthrough build is called
*
*
*/
struct scic_smp_passthru_request_callbacks {
/**
* Common callbacks for all Passthru requests
*/
struct scic_passthru_request_callbacks common_callbacks;
/**
* Function pointer to get the length of the smp request and its length
*/
u32 (*scic_cb_smp_passthru_get_request)(void *, u8 **);
/**
* Function pointer to get the frame type of the smp request
*/
u8 (*scic_cb_smp_passthru_get_frame_type)(void *);
/**
* Function pointer to get the function in the the smp request
*/
u8 (*scic_cb_smp_passthru_get_function)(void *);
/**
* Function pointer to get the "allocated response length" in the the smp request
*/
u8 (*scic_cb_smp_passthru_get_allocated_response_length)(void *);
};
/**
* This enumeration specifies the transport protocol utilized for the request.
*
*
*/
typedef enum {
/**
* This enumeration constant indicates that no protocol has yet been
* set.
*/
SCIC_NO_PROTOCOL,
/**
* This enumeration constant indicates that the protocol utilized
* is the Serial Management Protocol.
*/
SCIC_SMP_PROTOCOL,
/**
* This enumeration constant indicates that the protocol utilized
* is the Serial SCSI Protocol.
*/
SCIC_SSP_PROTOCOL,
/**
* This enumeration constant indicates that the protocol utilized
* is the Serial-ATA Tunneling Protocol.
*/
SCIC_STP_PROTOCOL
} SCIC_TRANSPORT_PROTOCOL;
/**
* scic_io_request_get_object_size() - This method simply returns the size
* required to build an SCI based IO request object.
*
* Return the size of the SCI IO request object.
*/
u32 scic_io_request_get_object_size(
void);
/**
* scic_io_request_construct() - This method is called by the SCI user to
* construct all SCI Core IO requests. Memory initialization and
* functionality common to all IO request types is performed in this method.
* @scic_controller: the handle to the core controller object for which to
* build an IO request.
* @scic_remote_device: the handle to the core remote device object for which
* to build an IO request.
* @io_tag: This parameter specifies the IO tag to be associated with this
* request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the
* request is built internally. The request will be copied into the actual
* controller request memory when the IO tag is allocated internally during
* the scic_controller_start_io() method.
* @user_io_request_object: This parameter specifies the user IO request to be
* utilized during IO construction. This IO pointer will become the
* associated object for the core IO request object.
* @scic_io_request_memory: This parameter specifies the memory location to be
* utilized when building the core request.
* @new_scic_io_request_handle: This parameter specifies a pointer to the
* handle the core will expect in further interactions with the core IO
* request object.
*
* The SCI core implementation will create an association between the user IO
* request object and the core IO request object. Indicate if the controller
* successfully built the IO request. SCI_SUCCESS This value is returned if the
* IO request was successfully built.
*/
enum sci_status scic_io_request_construct(
struct scic_sds_controller *scic_controller,
struct scic_sds_remote_device *scic_remote_device,
u16 io_tag,
void *user_io_request_object,
void *scic_io_request_memory,
struct scic_sds_request **new_scic_io_request_handle);
/**
* scic_io_request_construct_basic_ssp() - This method is called by the SCI
* user to build an SSP IO request.
* @scic_io_request: This parameter specifies the handle to the io request
* object to be built.
*
* - The user must have previously called scic_io_request_construct() on the
* supplied IO request. Indicate if the controller successfully built the IO
* request. SCI_SUCCESS This value is returned if the IO request was
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
* if the remote_device does not support the SSP protocol.
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
* properly set the association between the SCIC IO request and the user's IO
* request. Please refer to the sci_object_set_association() routine for more
* information.
*/
enum sci_status scic_io_request_construct_basic_ssp(
struct scic_sds_request *scic_io_request);
/**
* scic_io_request_construct_basic_sata() - This method is called by the SCI
* Core user to build an STP IO request.
* @scic_io_request: This parameter specifies the handle to the io request
* object to be built.
*
* - The user must have previously called scic_io_request_construct() on the
* supplied IO request. Indicate if the controller successfully built the IO
* request. SCI_SUCCESS This value is returned if the IO request was
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
* if the remote_device does not support the STP protocol.
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
* properly set the association between the SCIC IO request and the user's IO
* request. Please refer to the sci_object_set_association() routine for more
* information.
*/
enum sci_status scic_io_request_construct_basic_sata(
struct scic_sds_request *scic_io_request);
/**
* scic_io_request_construct_smp() - This method is called by the SCI user to
* build an SMP IO request.
* @scic_io_request: This parameter specifies the handle to the io request
* object to be built.
*
* - The user must have previously called scic_io_request_construct() on the
* supplied IO request. Indicate if the controller successfully built the IO
* request. SCI_SUCCESS This value is returned if the IO request was
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
* if the remote_device does not support the SMP protocol.
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
* properly set the association between the SCIC IO request and the user's IO
* request. Please refer to the sci_object_set_association() routine for more
* information.
*/
enum sci_status scic_io_request_construct_smp(
struct scic_sds_request *scic_io_request);
/**
* scic_request_get_controller_status() - This method returns the controller
* specific IO/Task request status. These status values are unique to the
* specific controller being managed by the SCIC.
* @io_request: the handle to the IO or task management request object for
* which to retrieve the status.
*
* This method returns a value indicating the controller specific request
* status.
*/
u32 scic_request_get_controller_status(
struct scic_sds_request *io_request);
/**
* scic_io_request_get_command_iu_address() - This method will return the
* address to the command information unit.
* @scic_io_request: This parameter specifies the handle to the io request
* object to be built.
*
* The address of the SSP/SMP command information unit.
*/
void *scic_io_request_get_command_iu_address(
struct scic_sds_request *scic_io_request);
/**
* scic_io_request_get_response_iu_address() - This method will return the
* address to the response information unit. For an SSP request this buffer
* is only valid if the IO request is completed with the status
* SCI_FAILURE_IO_RESPONSE_VALID.
* @scic_io_request: This parameter specifies the handle to the io request
* object to be built.
*
* The address of the SSP/SMP response information unit.
*/
void *scic_io_request_get_response_iu_address(
struct scic_sds_request *scic_io_request);
/**
* scic_io_request_get_io_tag() - This method will return the IO tag utilized
* by the IO request.
* @scic_io_request: This parameter specifies the handle to the io request
* object for which to return the IO tag.
*
* An unsigned integer representing the IO tag being utilized.
* SCI_CONTROLLER_INVALID_IO_TAG This value is returned if the IO does not
* currently have an IO tag allocated to it. All return other values indicate a
* legitimate tag.
*/
u16 scic_io_request_get_io_tag(
struct scic_sds_request *scic_io_request);
/**
* scic_stp_io_request_set_ncq_tag() - This method will assign an NCQ tag to
* the io request object. The caller of this function must make sure that
* only valid NCQ tags are assigned to the io request object.
* @scic_io_request: This parameter specifies the handle to the io request
* object to which to assign the ncq tag.
* @ncq_tag: This parameter specifies the NCQ tag to be utilized for the
* supplied core IO request. It is up to the user to make sure that this is
* a valid NCQ tag.
*
* none This function is only valid for SATA NCQ requests.
*/
void scic_stp_io_request_set_ncq_tag(
struct scic_sds_request *scic_io_request,
u16 ncq_tag);
/**
* scic_stp_io_request_get_h2d_reg_address() - This method will return the
* address of the host to device register fis region for the io request
* object.
* @scic_io_request: This parameter specifies the handle to the io request
* object from which to get the host to device register fis buffer.
*
* The address of the host to device register fis buffer in the io request
* object. This function is only valid for SATA requests.
*/
void *scic_stp_io_request_get_h2d_reg_address(
struct scic_sds_request *scic_io_request);
/**
* scic_stp_io_request_get_d2h_reg_address() - This method will return the
* address of the device to host register fis region for the io request
* object.
* @scic_io_request: This parameter specifies teh handle to the io request
* object from which to get the device to host register fis buffer.
*
* The address fo the device to host register fis ending the io request. This
* function is only valid for SATA requests.
*/
void *scic_stp_io_request_get_d2h_reg_address(
struct scic_sds_request *scic_io_request);
/**
* scic_io_request_get_number_of_bytes_transferred() - This method will return
* the number of bytes transferred from the SCU
* @scic_io_request: This parameter specifies the handle to the io request
* whose data length was not eqaul to the data length specified in the
* request. When the driver gets an early io completion status from the
* hardware, this routine should be called to get the actual number of bytes
* transferred
*
* The return is the number of bytes transferred when the data legth is not
* equal to the specified length in the io request
*/
u32 scic_io_request_get_number_of_bytes_transferred(
struct scic_sds_request *scic_io_request);
#endif /* _SCIC_IO_REQUEST_H_ */

View File

@ -0,0 +1,303 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_PHY_H_
#define _SCIC_PHY_H_
/**
* This file contains all of the interface methods that can be called by an
* SCIC user on a phy (SAS or SATA) object.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
#include "intel_sata.h"
#include "intel_sas.h"
struct scic_sds_phy;
struct scic_sds_port;
/**
* struct scic_phy_properties - This structure defines the properties common to
* all phys that can be retrieved.
*
*
*/
struct scic_phy_properties {
/**
* This field specifies the port that currently contains the
* supplied phy. This field may be set to SCI_INVALID_HANDLE
* if the phy is not currently contained in a port.
*/
struct scic_sds_port *owning_port;
/**
* This field specifies the link rate at which the phy is
* currently operating.
*/
enum sci_sas_link_rate negotiated_link_rate;
/**
* This field indicates the protocols supported by the phy.
*/
struct sci_sas_identify_address_frame_protocols protocols;
/**
* This field specifies the index of the phy in relation to other
* phys within the controller. This index is zero relative.
*/
u8 index;
};
/**
* struct scic_sas_phy_properties - This structure defines the properties,
* specific to a SAS phy, that can be retrieved.
*
*
*/
struct scic_sas_phy_properties {
/**
* This field delineates the Identify Address Frame received
* from the remote end point.
*/
struct sci_sas_identify_address_frame received_iaf;
/**
* This field delineates the Phy capabilities structure received
* from the remote end point.
*/
struct sas_capabilities received_capabilities;
};
/**
* struct scic_sata_phy_properties - This structure defines the properties,
* specific to a SATA phy, that can be retrieved.
*
*
*/
struct scic_sata_phy_properties {
/**
* This field delineates the signature FIS received from the
* attached target.
*/
struct sata_fis_reg_d2h signature_fis;
/**
* This field specifies to the user if a port selector is connected
* on the specified phy.
*/
bool is_port_selector_present;
};
/**
* enum scic_phy_counter_id - This enumeration depicts the various pieces of
* optional information that can be retrieved for a specific phy.
*
*
*/
enum scic_phy_counter_id {
/**
* This PHY information field tracks the number of frames received.
*/
SCIC_PHY_COUNTER_RECEIVED_FRAME,
/**
* This PHY information field tracks the number of frames transmitted.
*/
SCIC_PHY_COUNTER_TRANSMITTED_FRAME,
/**
* This PHY information field tracks the number of DWORDs received.
*/
SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD,
/**
* This PHY information field tracks the number of DWORDs transmitted.
*/
SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD,
/**
* This PHY information field tracks the number of times DWORD
* synchronization was lost.
*/
SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR,
/**
* This PHY information field tracks the number of received DWORDs with
* running disparity errors.
*/
SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR,
/**
* This PHY information field tracks the number of received frames with a
* CRC error (not including short or truncated frames).
*/
SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR,
/**
* This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
* primitives received.
*/
SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT,
/**
* This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
* primitives transmitted.
*/
SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT,
/**
* This PHY information field tracks the number of times the inactivity
* timer for connections on the phy has been utilized.
*/
SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED,
/**
* This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
* primitives received.
*/
SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT,
/**
* This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
* primitives transmitted.
*/
SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT,
/**
* This PHY information field tracks the number of CREDIT BLOCKED
* primitives received.
* @note Depending on remote device implementation, credit blocks
* may occur regularly.
*/
SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED,
/**
* This PHY information field contains the number of short frames
* received. A short frame is simply a frame smaller then what is
* allowed by either the SAS or SATA specification.
*/
SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME,
/**
* This PHY information field contains the number of frames received after
* credit has been exhausted.
*/
SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT,
/**
* This PHY information field contains the number of frames received after
* a DONE has been received.
*/
SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE,
/**
* This PHY information field contains the number of times the phy
* failed to achieve DWORD synchronization during speed negotiation.
*/
SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR
};
/**
* scic_sas_phy_get_properties() - This method will enable the user to retrieve
* information specific to a SAS phy, such as: the received identify address
* frame, received phy capabilities, etc.
* @phy: this parameter specifies the phy for which to retrieve properties.
* @properties: This parameter specifies the properties structure into which to
* copy the requested information.
*
* This method returns an indication as to whether the SAS phy properties were
* successfully retrieved. SCI_SUCCESS This value is returned if the SAS
* properties are successfully retrieved. SCI_FAILURE This value is returned if
* the SAS properties are not successfully retrieved (e.g. It's not a SAS Phy).
*/
enum sci_status scic_sas_phy_get_properties(
struct scic_sds_phy *phy,
struct scic_sas_phy_properties *properties);
/**
* scic_sata_phy_get_properties() - This method will enable the user to
* retrieve information specific to a SATA phy, such as: the received
* signature FIS, if a port selector is present, etc.
* @phy: this parameter specifies the phy for which to retrieve properties.
* @properties: This parameter specifies the properties structure into which to
* copy the requested information.
*
* This method returns an indication as to whether the SATA phy properties were
* successfully retrieved. SCI_SUCCESS This value is returned if the SATA
* properties are successfully retrieved. SCI_FAILURE This value is returned if
* the SATA properties are not successfully retrieved (e.g. It's not a SATA
* Phy).
*/
enum sci_status scic_sata_phy_get_properties(
struct scic_sds_phy *phy,
struct scic_sata_phy_properties *properties);
#endif /* _SCIC_PHY_H_ */

View File

@ -0,0 +1,213 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_PORT_H_
#define _SCIC_PORT_H_
/**
* This file contains all of the interface methods that can be called by an SCI
* Core user on a SAS or SATA port.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
#include "intel_sas.h"
struct scic_sds_port;
enum SCIC_PORT_NOT_READY_REASON_CODE {
SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS,
SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED,
SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION,
SCIC_PORT_NOT_READY_RECONFIGURING,
SCIC_PORT_NOT_READY_REASON_CODE_MAX
};
/**
* struct scic_port_end_point_properties - This structure defines the
* properties that can be retrieved for each end-point local or remote
* (attached) port in the controller.
*
*
*/
struct scic_port_end_point_properties {
/**
* This field indicates the SAS address for the associated end
* point in the port.
*/
struct sci_sas_address sas_address;
/**
* This field indicates the protocols supported by the associated
* end-point in the port.
*/
struct sci_sas_identify_address_frame_protocols protocols;
};
/**
* struct scic_port_properties - This structure defines the properties that can
* be retrieved for each port in the controller.
*
*
*/
struct scic_port_properties {
/**
* This field specifies the logical index of the port (0 relative).
*/
u32 index;
/**
* This field indicates the local end-point properties for port.
*/
struct scic_port_end_point_properties local;
/**
* This field indicates the remote (attached) end-point properties
* for the port.
*/
struct scic_port_end_point_properties remote;
/**
* This field specifies the phys contained inside the port.
*/
u32 phy_mask;
};
/**
* scic_port_get_properties() - This method simply returns the properties
* regarding the port, such as: physical index, protocols, sas address, etc.
* @port: this parameter specifies the port for which to retrieve the physical
* index.
* @properties: This parameter specifies the properties structure into which to
* copy the requested information.
*
* Indicate if the user specified a valid port. SCI_SUCCESS This value is
* returned if the specified port was valid. SCI_FAILURE_INVALID_PORT This
* value is returned if the specified port is not valid. When this value is
* returned, no data is copied to the properties output parameter.
*/
enum sci_status scic_port_get_properties(
struct scic_sds_port *port,
struct scic_port_properties *properties);
/**
* scic_port_start() - This method will make the port ready for operation.
* Prior to calling the start method IO operation is not possible.
* @port: This parameter specifies the port to be started.
*
* Indicate if the port was successfully started. SCI_SUCCESS This value is
* returned if the port was successfully started. SCI_WARNING_ALREADY_IN_STATE
* This value is returned if the port is in the process of starting.
* SCI_FAILURE_INVALID_PORT This value is returned if the supplied port is not
* valid. SCI_FAILURE_INVALID_STATE This value is returned if a start operation
* can't be completed due to the state of port.
*/
enum sci_status scic_port_start(
struct scic_sds_port *port);
/**
* scic_port_stop() - This method will make the port no longer ready for
* operation. After invoking this method IO operation is not possible.
* @port: This parameter specifies the port to be stopped.
*
* Indicate if the port was successfully stopped. SCI_SUCCESS This value is
* returned if the port was successfully stopped. SCI_WARNING_ALREADY_IN_STATE
* This value is returned if the port is already stopped or in the process of
* stopping. SCI_FAILURE_INVALID_PORT This value is returned if the supplied
* port is not valid. SCI_FAILURE_INVALID_STATE This value is returned if a
* stop operation can't be completed due to the state of port.
*/
enum sci_status scic_port_stop(
struct scic_sds_port *port);
/**
* scic_port_hard_reset() - This method will request the SCI implementation to
* perform a HARD RESET on the SAS Port. If/When the HARD RESET completes
* the SCI user will be notified via an SCI OS callback indicating a direct
* attached device was found.
* @port: a handle corresponding to the SAS port to be hard reset.
* @reset_timeout: This parameter specifies the number of milliseconds in which
* the port reset operation should complete.
*
* The SCI User callback in SCIC_USER_CALLBACKS_T will only be called once for
* each phy in the SAS Port at completion of the hard reset sequence. Return a
* status indicating whether the hard reset started successfully. SCI_SUCCESS
* This value is returned if the hard reset operation started successfully.
*/
enum sci_status scic_port_hard_reset(
struct scic_sds_port *port,
u32 reset_timeout);
/**
* scic_port_enable_broadcast_change_notification() - This API method enables
* the broadcast change notification from underneath hardware.
* @port: The port upon which broadcast change notifications (BCN) are to be
* enabled.
*
*/
void scic_port_enable_broadcast_change_notification(
struct scic_sds_port *port);
#endif /* _SCIC_PORT_H_ */

View File

@ -0,0 +1,295 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_REMOTE_DEVICE_H_
#define _SCIC_REMOTE_DEVICE_H_
/**
* This file contains all of the interface methods that can be called by an
* SCIC user on the device object.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
#include "intel_sas.h"
struct scic_sds_port;
struct scic_sds_remote_device;
/**
*
*
*
*/
enum scic_remote_device_not_ready_reason_code {
SCIC_REMOTE_DEVICE_NOT_READY_START_REQUESTED,
SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED,
SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED,
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED,
SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED,
SCIC_REMOTE_DEVICE_NOT_READY_REASON_CODE_MAX
};
/**
* scic_remote_device_get_object_size() - This method simply returns the
* maximum memory space needed to store a remote device object.
*
* a positive integer value indicating the size (in bytes) of the remote device
* object.
*/
u32 scic_remote_device_get_object_size(
void);
struct scic_sds_port;
struct scic_sds_remote_device;
/**
* scic_remote_device_construct() - This method will perform the construction
* common to all remote device objects.
* @sci_port: SAS/SATA port through which this device is accessed.
* @sci_dev: remote device to construct
*
* It isn't necessary to call scic_remote_device_destruct() for device objects
* that have only called this method for construction. Once subsequent
* construction methods have been invoked (e.g.
* scic_remote_device_da_construct()), then destruction should occur. none
*/
void scic_remote_device_construct(struct scic_sds_port *sci_port,
struct scic_sds_remote_device *sci_dev);
/**
* scic_remote_device_da_construct() - This method will construct a
* SCIC_REMOTE_DEVICE object for a direct attached (da) device. The
* information (e.g. IAF, Signature FIS, etc.) necessary to build the device
* is known to the SCI Core since it is contained in the scic_phy object.
* @remote_device: This parameter specifies the remote device to be destructed.
*
* The user must have previously called scic_remote_device_construct() Remote
* device objects are a limited resource. As such, they must be protected.
* Thus calls to construct and destruct are mutually exclusive and
* non-reentrant. Indicate if the remote device was successfully constructed.
* SCI_SUCCESS Returned if the device was successfully constructed.
* SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been
* constructed. If it's an additional phy for the target, then call
* scic_remote_device_da_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned
* if the supplied parameters necessitate creation of a remote device for which
* the protocol is not supported by the underlying controller hardware.
* SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core
* controller associated with the supplied parameters is unable to support
* additional remote devices.
*/
enum sci_status scic_remote_device_da_construct(
struct scic_sds_remote_device *remote_device);
/**
* scic_remote_device_ea_construct() - This method will construct an
* SCIC_REMOTE_DEVICE object for an expander attached (ea) device from an
* SMP Discover Response.
* @remote_device: This parameter specifies the remote device to be destructed.
* @discover_response: This parameter specifies the SMP Discovery Response to
* be used in device creation.
*
* The user must have previously called scic_remote_device_construct() Remote
* device objects are a limited resource. As such, they must be protected.
* Thus calls to construct and destruct are mutually exclusive and
* non-reentrant. Indicate if the remote device was successfully constructed.
* SCI_SUCCESS Returned if the device was successfully constructed.
* SCI_FAILURE_DEVICE_EXISTS Returned if the device has already been
* constructed. If it's an additional phy for the target, then call
* scic_ea_remote_device_add_phy(). SCI_FAILURE_UNSUPPORTED_PROTOCOL Returned
* if the supplied parameters necessitate creation of a remote device for which
* the protocol is not supported by the underlying controller hardware.
* SCI_FAILURE_INSUFFICIENT_RESOURCES This value is returned if the core
* controller associated with the supplied parameters is unable to support
* additional remote devices.
*/
enum sci_status scic_remote_device_ea_construct(
struct scic_sds_remote_device *remote_device,
struct smp_response_discover *discover_response);
/**
* scic_remote_device_destruct() - This method is utilized to free up a core's
* remote device object.
* @remote_device: This parameter specifies the remote device to be destructed.
*
* Remote device objects are a limited resource. As such, they must be
* protected. Thus calls to construct and destruct are mutually exclusive and
* non-reentrant. The return value shall indicate if the device was
* successfully destructed or if some failure occurred. enum sci_status This value
* is returned if the device is successfully destructed.
* SCI_FAILURE_INVALID_REMOTE_DEVICE This value is returned if the supplied
* device isn't valid (e.g. it's already been destoryed, the handle isn't
* valid, etc.).
*/
enum sci_status scic_remote_device_destruct(
struct scic_sds_remote_device *remote_device);
/**
* scic_remote_device_start() - This method will start the supplied remote
* device. This method enables normal IO requests to flow through to the
* remote device.
* @remote_device: This parameter specifies the device to be started.
* @timeout: This parameter specifies the number of milliseconds in which the
* start operation should complete.
*
* An indication of whether the device was successfully started. SCI_SUCCESS
* This value is returned if the device was successfully started.
* SCI_FAILURE_INVALID_PHY This value is returned if the user attempts to start
* the device when there have been no phys added to it.
*/
enum sci_status scic_remote_device_start(
struct scic_sds_remote_device *remote_device,
u32 timeout);
/**
* scic_remote_device_stop() - This method will stop both transmission and
* reception of link activity for the supplied remote device. This method
* disables normal IO requests from flowing through to the remote device.
* @remote_device: This parameter specifies the device to be stopped.
* @timeout: This parameter specifies the number of milliseconds in which the
* stop operation should complete.
*
* An indication of whether the device was successfully stopped. SCI_SUCCESS
* This value is returned if the transmission and reception for the device was
* successfully stopped.
*/
enum sci_status scic_remote_device_stop(
struct scic_sds_remote_device *remote_device,
u32 timeout);
/**
* scic_remote_device_reset() - This method will reset the device making it
* ready for operation. This method must be called anytime the device is
* reset either through a SMP phy control or a port hard reset request.
* @remote_device: This parameter specifies the device to be reset.
*
* This method does not actually cause the device hardware to be reset. This
* method resets the software object so that it will be operational after a
* device hardware reset completes. An indication of whether the device reset
* was accepted. SCI_SUCCESS This value is returned if the device reset is
* started.
*/
enum sci_status scic_remote_device_reset(
struct scic_sds_remote_device *remote_device);
/**
* scic_remote_device_reset_complete() - This method informs the device object
* that the reset operation is complete and the device can resume operation
* again.
* @remote_device: This parameter specifies the device which is to be informed
* of the reset complete operation.
*
* An indication that the device is resuming operation. SCI_SUCCESS the device
* is resuming operation.
*/
enum sci_status scic_remote_device_reset_complete(
struct scic_sds_remote_device *remote_device);
/**
* scic_remote_device_get_connection_rate() - This method simply returns the
* link rate at which communications to the remote device occur.
* @remote_device: This parameter specifies the device for which to get the
* connection rate.
*
* Return the link rate at which we transfer for the supplied remote device.
*/
enum sci_sas_link_rate scic_remote_device_get_connection_rate(
struct scic_sds_remote_device *remote_device);
/**
* scic_remote_device_get_protocols() - This method will indicate which
* protocols are supported by this remote device.
* @remote_device: This parameter specifies the device for which to return the
* protocol.
* @protocols: This parameter specifies the output values, from the remote
* device object, which indicate the protocols supported by the supplied
* remote_device.
*
* The type of protocols supported by this device. The values are returned as
* part of a bit mask in order to allow for multi-protocol support.
*/
void scic_remote_device_get_protocols(
struct scic_sds_remote_device *remote_device,
struct smp_discover_response_protocols *protocols);
#if !defined(DISABLE_ATAPI)
/**
* scic_remote_device_is_atapi() -
* @this_device: The device whose type is to be decided.
*
* This method first decide whether a device is a stp target, then decode the
* signature fis of a DA STP device to tell whether it is a standard end disk
* or an ATAPI device. bool Indicate a device is ATAPI device or not.
*/
bool scic_remote_device_is_atapi(
struct scic_sds_remote_device *device_handle);
#else /* !defined(DISABLE_ATAPI) */
#define scic_remote_device_is_atapi(device_handle) false
#endif /* !defined(DISABLE_ATAPI) */
#endif /* _SCIC_REMOTE_DEVICE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,706 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_CONTROLLER_H_
#define _SCIC_SDS_CONTROLLER_H_
/**
* This file contains the structures, constants and prototypes used for the
* core controller object.
*
*
*/
#include "sci_pool.h"
#include "sci_controller_constants.h"
#include "sci_memory_descriptor_list.h"
#include "sci_base_controller.h"
#include "scic_config_parameters.h"
#include "scic_sds_port.h"
#include "scic_sds_phy.h"
#include "scic_sds_remote_node_table.h"
#include "scu_registers.h"
#include "scu_constants.h"
#include "scu_remote_node_context.h"
#include "scu_task_context.h"
#include "scu_unsolicited_frame.h"
#include "scic_sds_unsolicited_frame_control.h"
#include "scic_sds_port_configuration_agent.h"
#include "scic_sds_pci.h"
struct scic_sds_remote_device;
struct scic_sds_request;
struct scic_sds_controller;
#define SCU_COMPLETION_RAM_ALIGNMENT (64)
/**
* enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS -
*
* This enumeration depects the types of MDEs that are going to be created for
* the controller object.
*/
enum SCIC_SDS_CONTROLLER_MEMORY_DESCRIPTORS {
/**
* Completion queue MDE entry
*/
SCU_MDE_COMPLETION_QUEUE,
/**
* Remote node context MDE entry
*/
SCU_MDE_REMOTE_NODE_CONTEXT,
/**
* Task context MDE entry
*/
SCU_MDE_TASK_CONTEXT,
/**
* Unsolicited frame buffer MDE entrys this is the start of the unsolicited
* frame buffer entries.
*/
SCU_MDE_UF_BUFFER,
SCU_MAX_MDES
};
/**
*
*
* Allowed PORT configuration modes APC Automatic PORT configuration mode is
* defined by the OEM configuration parameters providing no PHY_MASK parameters
* for any PORT. i.e. There are no phys assigned to any of the ports at start.
* MPC Manual PORT configuration mode is defined by the OEM configuration
* parameters providing a PHY_MASK value for any PORT. It is assumed that any
* PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned.
* A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs
* being assigned is sufficient to declare manual PORT configuration.
*/
enum SCIC_PORT_CONFIGURATION_MODE {
SCIC_PORT_MANUAL_CONFIGURATION_MODE,
SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE
};
/**
* struct scic_power_control -
*
* This structure defines the fields for managing power control for direct
* attached disk devices.
*/
struct scic_power_control {
/**
* This field is set when the power control timer is running and cleared when
* it is not.
*/
bool timer_started;
/**
* This field is the handle to the driver timer object. This timer is used to
* control when the directed attached disks can consume power.
*/
void *timer;
/**
* This field is used to keep track of how many phys are put into the
* requesters field.
*/
u8 phys_waiting;
/**
* This field is an array of phys that we are waiting on. The phys are direct
* mapped into requesters via struct scic_sds_phy.phy_index
*/
struct scic_sds_phy *requesters[SCI_MAX_PHYS];
};
/**
* struct scic_sds_controller -
*
* This structure represents the SCU contoller object.
*/
struct scic_sds_controller {
/**
* The struct sci_base_controller is the parent object for the struct scic_sds_controller
* object.
*/
struct sci_base_controller parent;
/**
* This field is the driver timer object handler used to time the controller
* object start and stop requests.
*/
void *timeout_timer;
/**
* This field contains the user parameters to be utilized for this
* core controller object.
*/
union scic_user_parameters user_parameters;
/**
* This field contains the OEM parameters to be utilized for this
* core controller object.
*/
union scic_oem_parameters oem_parameters;
/**
* This field contains the port configuration agent for this controller.
*/
struct scic_sds_port_configuration_agent port_agent;
/**
* This field is the array of port objects that are controlled by this
* controller object. There is one dummy port object also contained within
* this controller object.
*/
struct scic_sds_port port_table[SCI_MAX_PORTS + 1];
/**
* This field is the array of phy objects that are controlled by this
* controller object.
*/
struct scic_sds_phy phy_table[SCI_MAX_PHYS];
/**
* This field is the array of device objects that are currently constructed
* for this controller object. This table is used as a fast lookup of device
* objects that need to handle device completion notifications from the
* hardware. The table is RNi based.
*/
struct scic_sds_remote_device *device_table[SCI_MAX_REMOTE_DEVICES];
/**
* This field is the array of IO request objects that are currently active for
* this controller object. This table is used as a fast lookup of the io
* request object that need to handle completion queue notifications. The
* table is TCi based.
*/
struct scic_sds_request *io_request_table[SCI_MAX_IO_REQUESTS];
/**
* This field is the free RNi data structure
*/
struct scic_remote_node_table available_remote_nodes;
/**
* This field is the TCi pool used to manage the task context index.
*/
SCI_POOL_CREATE(tci_pool, u16, SCI_MAX_IO_REQUESTS);
/**
* This filed is the struct scic_power_control data used to controll when direct
* attached devices can consume power.
*/
struct scic_power_control power_control;
/**
* This field is the array of sequence values for the IO Tag fields. Even
* though only 4 bits of the field is used for the sequence the sequence is 16
* bits in size so the sequence can be bitwise or'd with the TCi to build the
* IO Tag value.
*/
u16 io_request_sequence[SCI_MAX_IO_REQUESTS];
/**
* This field in the array of sequence values for the RNi. These are used
* to control io request build to io request start operations. The sequence
* value is recorded into an io request when it is built and is checked on
* the io request start operation to make sure that there was not a device
* hot plug between the build and start operation.
*/
u8 remote_device_sequence[SCI_MAX_REMOTE_DEVICES];
/**
* This field is a pointer to the memory allocated by the driver for the task
* context table. This data is shared between the hardware and software.
*/
struct scu_task_context *task_context_table;
/**
* This field is a pointer to the memory allocated by the driver for the
* remote node context table. This table is shared between the hardware and
* software.
*/
union scu_remote_node_context *remote_node_context_table;
/**
* This field is the array of physical memory requiremets for this controller
* object.
*/
struct sci_physical_memory_descriptor memory_descriptors[SCU_MAX_MDES];
/**
* This field is a pointer to the completion queue. This memory is
* written to by the hardware and read by the software.
*/
u32 *completion_queue;
/**
* This field is the software copy of the completion queue get pointer. The
* controller object writes this value to the hardware after processing the
* completion entries.
*/
u32 completion_queue_get;
/**
* This field is the minimum of the number of hardware supported port entries
* and the software requested port entries.
*/
u32 logical_port_entries;
/**
* This field is the minimum number of hardware supported completion queue
* entries and the software requested completion queue entries.
*/
u32 completion_queue_entries;
/**
* This field is the minimum number of hardware supported event entries and
* the software requested event entries.
*/
u32 completion_event_entries;
/**
* This field is the minimum number of devices supported by the hardware and
* the number of devices requested by the software.
*/
u32 remote_node_entries;
/**
* This field is the minimum number of IO requests supported by the hardware
* and the number of IO requests requested by the software.
*/
u32 task_context_entries;
/**
* This object contains all of the unsolicited frame specific
* data utilized by the core controller.
*/
struct scic_sds_unsolicited_frame_control uf_control;
/**
* This field records the fact that the controller has encountered a fatal
* error and must be reset.
*/
bool encountered_fatal_error;
/**
* This field specifies that the controller should ignore
* completion processing for non-fastpath events. This will
* cause the completions to be thrown away.
*/
bool restrict_completions;
/* Phy Startup Data */
/**
* This field is the driver timer handle for controller phy request startup.
* On controller start the controller will start each PHY individually in
* order of phy index.
*/
void *phy_startup_timer;
/**
* This field is set when the phy_startup_timer is running and is cleared when
* the phy_startup_timer is stopped.
*/
bool phy_startup_timer_pending;
/**
* This field is the index of the next phy start. It is initialized to 0 and
* increments for each phy index that is started.
*/
u32 next_phy_to_start;
/**
* This field controlls the invalid link up notifications to the SCI_USER. If
* an invalid_link_up notification is reported a bit for the PHY index is set
* so further notifications are not made. Once the PHY object reports link up
* and is made part of a port then this bit for the PHY index is cleared.
*/
u8 invalid_phy_mask;
/*
* This field saves the current interrupt coalescing number of the controller.
*/
u16 interrupt_coalesce_number;
/*
* This field saves the current interrupt coalescing timeout value in microseconds.
*/
u32 interrupt_coalesce_timeout;
/**
* This field is a pointer to the memory mapped register space for the
* struct smu_registers.
*/
struct smu_registers __iomem *smu_registers;
/**
* This field is a pointer to the memory mapped register space for the
* struct scu_registers.
*/
struct scu_registers __iomem *scu_registers;
};
typedef void (*scic_sds_controller_phy_handler_t)(struct scic_sds_controller *,
struct scic_sds_port *,
struct scic_sds_phy *);
/**
* struct scic_sds_controller_state_handler -
*
* This structure contains the SDS core specific definition for the state
* handlers.
*/
struct scic_sds_controller_state_handler {
struct sci_base_controller_state_handler base;
sci_base_controller_request_handler_t terminate_request;
scic_sds_controller_phy_handler_t link_up;
scic_sds_controller_phy_handler_t link_down;
};
extern const struct scic_sds_controller_state_handler
scic_sds_controller_state_handler_table[];
extern const struct sci_base_state scic_sds_controller_state_table[];
/**
* INCREMENT_QUEUE_GET() -
*
* This macro will increment the specified index to and if the index wraps to 0
* it will toggel the cycle bit.
*/
#define INCREMENT_QUEUE_GET(index, cycle, entry_count, bit_toggle) \
{ \
if ((index) + 1 == entry_count) { \
(index) = 0; \
(cycle) = (cycle) ^ (bit_toggle); \
} else { \
index = index + 1; \
} \
}
/**
* scic_sds_controller_get_base_state_machine() -
*
* This is a helper macro that gets the base state machine for the controller
* object
*/
#define scic_sds_controller_get_base_state_machine(this_controller) \
(&(this_controller)->parent.state_machine)
/**
* scic_sds_controller_get_port_configuration_agent() -
*
* This is a helper macro to get the port configuration agent from the
* controller object.
*/
#define scic_sds_controller_get_port_configuration_agent(controller) \
(&(controller)->port_agent)
/**
* smu_register_write() -
*
* This macro writes to the smu_register for this controller
*/
#define smu_register_write(controller, reg, value) \
scic_sds_pci_write_smu_dword((controller), &(reg), (value))
/**
* smu_register_read() -
*
* This macro reads the smu_register for this controller
*/
#define smu_register_read(controller, reg) \
scic_sds_pci_read_smu_dword((controller), &(reg))
/**
* scu_register_write() -
*
* This mcaro writes the scu_register for this controller
*/
#define scu_register_write(controller, reg, value) \
scic_sds_pci_write_scu_dword((controller), &(reg), (value))
/**
* scu_register_read() -
*
* This macro reads the scu_register for this controller
*/
#define scu_register_read(controller, reg) \
scic_sds_pci_read_scu_dword((controller), &(reg))
/**
* scic_sds_controller_get_protocol_engine_group() -
*
* This macro returns the protocol engine group for this controller object.
* Presently we only support protocol engine group 0 so just return that
*/
#define scic_sds_controller_get_protocol_engine_group(controller) 0
/**
* scic_sds_io_tag_construct() -
*
* This macro constructs an IO tag from the sequence and index values.
*/
#define scic_sds_io_tag_construct(sequence, task_index) \
((sequence) << 12 | (task_index))
/**
* scic_sds_io_tag_get_sequence() -
*
* This macro returns the IO sequence from the IO tag value.
*/
#define scic_sds_io_tag_get_sequence(io_tag) \
(((io_tag) & 0xF000) >> 12)
/**
* scic_sds_io_tag_get_index() -
*
* This macro returns the TCi from the io tag value
*/
#define scic_sds_io_tag_get_index(io_tag) \
((io_tag) & 0x0FFF)
/**
* scic_sds_io_sequence_increment() -
*
* This is a helper macro to increment the io sequence count. We may find in
* the future that it will be faster to store the sequence count in such a way
* as we dont perform the shift operation to build io tag values so therefore
* need a way to incrment them correctly
*/
#define scic_sds_io_sequence_increment(value) \
((value) = (((value) + 1) & 0x000F))
#define scic_sds_remote_device_node_count(device) \
(\
(\
(device)->target_protocols.u.bits.attached_stp_target \
&& ((device)->is_direct_attached != true) \
) \
? SCU_STP_REMOTE_NODE_COUNT : SCU_SSP_REMOTE_NODE_COUNT \
)
/**
* scic_sds_controller_set_invalid_phy() -
*
* This macro will set the bit in the invalid phy mask for this controller
* object. This is used to control messages reported for invalid link up
* notifications.
*/
#define scic_sds_controller_set_invalid_phy(controller, phy) \
((controller)->invalid_phy_mask |= (1 << (phy)->phy_index))
/**
* scic_sds_controller_clear_invalid_phy() -
*
* This macro will clear the bit in the invalid phy mask for this controller
* object. This is used to control messages reported for invalid link up
* notifications.
*/
#define scic_sds_controller_clear_invalid_phy(controller, phy) \
((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))
/* --------------------------------------------------------------------------- */
u32 scic_sds_controller_get_object_size(void);
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
enum SCIC_PORT_CONFIGURATION_MODE scic_sds_controller_get_port_configuration_mode(
struct scic_sds_controller *this_controller);
/* --------------------------------------------------------------------------- */
void scic_sds_controller_post_request(
struct scic_sds_controller *this_controller,
u32 request);
/* --------------------------------------------------------------------------- */
void scic_sds_controller_release_frame(
struct scic_sds_controller *this_controller,
u32 frame_index);
void scic_sds_controller_copy_sata_response(
void *response_buffer,
void *frame_header,
void *frame_buffer);
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_controller_allocate_remote_node_context(
struct scic_sds_controller *this_controller,
struct scic_sds_remote_device *the_device,
u16 *node_id);
void scic_sds_controller_free_remote_node_context(
struct scic_sds_controller *this_controller,
struct scic_sds_remote_device *the_device,
u16 node_id);
union scu_remote_node_context *scic_sds_controller_get_remote_node_context_buffer(
struct scic_sds_controller *this_controller,
u16 node_id);
/* --------------------------------------------------------------------------- */
struct scic_sds_request *scic_sds_controller_get_io_request_from_tag(
struct scic_sds_controller *this_controller,
u16 io_tag);
struct scu_task_context *scic_sds_controller_get_task_context_buffer(
struct scic_sds_controller *this_controller,
u16 io_tag);
/*
* *****************************************************************************
* * CORE CONTROLLER POWER CONTROL METHODS
* ***************************************************************************** */
void scic_sds_controller_power_control_queue_insert(
struct scic_sds_controller *this_controller,
struct scic_sds_phy *the_phy);
void scic_sds_controller_power_control_queue_remove(
struct scic_sds_controller *this_controller,
struct scic_sds_phy *the_phy);
/*
* *****************************************************************************
* * CORE CONTROLLER PHY MESSAGE PROCESSING
* ***************************************************************************** */
void scic_sds_controller_link_up(
struct scic_sds_controller *this_controller,
struct scic_sds_port *the_port,
struct scic_sds_phy *the_phy);
void scic_sds_controller_link_down(
struct scic_sds_controller *this_controller,
struct scic_sds_port *the_port,
struct scic_sds_phy *the_phy);
/*
* *****************************************************************************
* * CORE CONTROLLER PRIVATE METHODS
* ***************************************************************************** */
enum sci_status scic_sds_controller_validate_memory_descriptor_table(
struct scic_sds_controller *this_controller);
void scic_sds_controller_ram_initialization(
struct scic_sds_controller *this_controller);
void scic_sds_controller_assign_task_entries(
struct scic_sds_controller *this_controller);
void scic_sds_controller_afe_initialization(
struct scic_sds_controller *this_controller);
void scic_sds_controller_enable_port_task_scheduler(
struct scic_sds_controller *this_controller);
void scic_sds_controller_initialize_completion_queue(
struct scic_sds_controller *this_controller);
void scic_sds_controller_initialize_unsolicited_frame_queue(
struct scic_sds_controller *this_controller);
void scic_sds_controller_phy_timer_stop(
struct scic_sds_controller *this_controller);
enum sci_status scic_sds_controller_start_next_phy(
struct scic_sds_controller *this_controller);
enum sci_status scic_sds_controller_stop_phys(
struct scic_sds_controller *this_controller);
enum sci_status scic_sds_controller_stop_ports(
struct scic_sds_controller *this_controller);
enum sci_status scic_sds_controller_stop_devices(
struct scic_sds_controller *this_controller);
void scic_sds_controller_copy_task_context(
struct scic_sds_controller *this_controller,
struct scic_sds_request *this_request);
void scic_sds_controller_timeout_handler(
struct scic_sds_controller *controller);
void scic_sds_controller_initialize_power_control(
struct scic_sds_controller *this_controller);
void scic_sds_controller_register_setup(
struct scic_sds_controller *this_controller);
void scic_sds_controller_reset_hardware(
struct scic_sds_controller *this_controller);
void scic_sds_controller_initialize_phy_startup(
struct scic_sds_controller *this_controller);
#endif /* _SCIC_SDS_CONTROLLER_H_ */

View File

@ -0,0 +1,463 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_CONTROLLER_REGISTERS_H_
#define _SCIC_SDS_CONTROLLER_REGISTERS_H_
/**
* This file contains macros used to perform the register reads/writes to the
* SCU hardware.
*
*
*/
#include "scu_registers.h"
#include "scic_sds_controller.h"
/**
* scic_sds_controller_smu_register_read() -
*
* SMU_REGISTER_ACCESS_MACROS
*/
#define scic_sds_controller_smu_register_read(controller, reg) \
smu_register_read(\
(controller), \
(controller)->smu_registers->reg \
)
#define scic_sds_controller_smu_register_write(controller, reg, value) \
smu_register_write(\
(controller), \
(controller)->smu_registers->reg, \
(value) \
)
/**
* scu_afe_register_write() -
*
* AFE_REGISTER_ACCESS_MACROS
*/
#define scu_afe_register_write(controller, reg, value) \
scu_register_write(\
(controller), \
(controller)->scu_registers->afe.reg, \
(value) \
)
#define scu_afe_txreg_write(controller, phy, reg, value) \
scu_register_write(\
(controller), \
(controller)->scu_registers->afe.scu_afe_xcvr[phy].reg,\
(value) \
)
#define scu_afe_register_read(controller, reg) \
scu_register_read(\
(controller), \
(controller)->scu_registers->afe.reg \
)
/**
* scu_controller_viit_register_write() -
*
* VIIT_REGISTER_ACCESS_MACROS
*/
#define scu_controller_viit_register_write(controller, index, reg, value) \
scu_register_write(\
(controller), \
(controller)->scu_registers->peg0.viit[index].reg, \
value \
)
/*
* *****************************************************************************
* * SMU REGISTERS
* ***************************************************************************** */
/**
* SMU_PCP_WRITE() -
*
* struct smu_registers
*/
#define SMU_PCP_WRITE(controller, value) \
scic_sds_controller_smu_register_write(\
controller, post_context_port, value \
)
#define SMU_TCR_READ(controller, value) \
scic_sds_controller_smu_register_read(\
controller, task_context_range \
)
#define SMU_TCR_WRITE(controller, value) \
scic_sds_controller_smu_register_write(\
controller, task_context_range, value \
)
#define SMU_HTTBAR_WRITE(controller, address) \
{ \
scic_sds_controller_smu_register_write(\
controller, \
host_task_table_lower, \
lower_32_bits(address) \
); \
scic_sds_controller_smu_register_write(\
controller, \
host_task_table_upper, \
upper_32_bits(address) \
); \
}
#define SMU_CQBAR_WRITE(controller, address) \
{ \
scic_sds_controller_smu_register_write(\
controller, \
completion_queue_lower, \
lower_32_bits(address) \
); \
scic_sds_controller_smu_register_write(\
controller, \
completion_queue_upper, \
upper_32_bits(address) \
); \
}
#define SMU_CQGR_WRITE(controller, value) \
scic_sds_controller_smu_register_write(\
controller, completion_queue_get, value \
)
#define SMU_CQGR_READ(controller, value) \
scic_sds_controller_smu_register_read(\
controller, completion_queue_get \
)
#define SMU_CQPR_WRITE(controller, value) \
scic_sds_controller_smu_register_write(\
controller, completion_queue_put, value \
)
#define SMU_RNCBAR_WRITE(controller, address) \
{ \
scic_sds_controller_smu_register_write(\
controller, \
remote_node_context_lower, \
lower_32_bits(address) \
); \
scic_sds_controller_smu_register_write(\
controller, \
remote_node_context_upper, \
upper_32_bits(address) \
); \
}
#define SMU_AMR_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, address_modifier \
)
#define SMU_IMR_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, interrupt_mask \
)
#define SMU_IMR_WRITE(controller, mask) \
scic_sds_controller_smu_register_write(\
controller, interrupt_mask, mask \
)
#define SMU_ISR_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, interrupt_status \
)
#define SMU_ISR_WRITE(controller, status) \
scic_sds_controller_smu_register_write(\
controller, interrupt_status, status \
)
#define SMU_ICC_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, interrupt_coalesce_control \
)
#define SMU_ICC_WRITE(controller, value) \
scic_sds_controller_smu_register_write(\
controller, interrupt_coalesce_control, value \
)
#define SMU_CQC_WRITE(controller, value) \
scic_sds_controller_smu_register_write(\
controller, completion_queue_control, value \
)
#define SMU_SMUSRCR_WRITE(controller, value) \
scic_sds_controller_smu_register_write(\
controller, soft_reset_control, value \
)
#define SMU_TCA_WRITE(controller, index, value) \
scic_sds_controller_smu_register_write(\
controller, task_context_assignment[index], value \
)
#define SMU_TCA_READ(controller, index) \
scic_sds_controller_smu_register_read(\
controller, task_context_assignment[index] \
)
#define SMU_DCC_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, device_context_capacity \
)
#define SMU_DFC_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, device_function_capacity \
)
#define SMU_SMUCSR_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, control_status \
)
#define SMU_CQPR_READ(controller) \
scic_sds_controller_smu_register_read(\
controller, completion_queue_put \
)
/**
* scic_sds_controller_scu_register_read() -
*
* SCU_REGISTER_ACCESS_MACROS
*/
#define scic_sds_controller_scu_register_read(controller, reg) \
scu_register_read(\
(controller), \
(controller)->scu_registers->reg \
)
#define scic_sds_controller_scu_register_write(controller, reg, value) \
scu_register_write(\
(controller), \
(controller)->scu_registers->reg, \
(value) \
)
/*
* ****************************************************************************
* * SCU SDMA REGISTERS
* **************************************************************************** */
/**
* scu_sdma_register_read() -
*
* SCU_SDMA_REGISTER_ACCESS_MACROS
*/
#define scu_sdma_register_read(controller, reg) \
scu_register_read(\
(controller), \
(controller)->scu_registers->sdma.reg \
)
#define scu_sdma_register_write(controller, reg, value) \
scu_register_write(\
(controller), \
(controller)->scu_registers->sdma.reg, \
(value) \
)
/**
* SCU_PUFATHAR_WRITE() -
*
* struct scu_sdma_registers
*/
#define SCU_PUFATHAR_WRITE(controller, address) \
{ \
scu_sdma_register_write(\
controller, \
uf_address_table_lower, \
lower_32_bits(address) \
); \
scu_sdma_register_write(\
controller, \
uf_address_table_upper, \
upper_32_bits(address) \
); \
}
#define SCU_UFHBAR_WRITE(controller, address) \
{ \
scu_sdma_register_write(\
controller, \
uf_header_base_address_lower, \
lower_32_bits(address) \
); \
scu_sdma_register_write(\
controller, \
uf_header_base_address_upper, \
upper_32_bits(address) \
); \
}
#define SCU_UFQC_READ(controller) \
scu_sdma_register_read(\
controller, \
unsolicited_frame_queue_control \
)
#define SCU_UFQC_WRITE(controller, value) \
scu_sdma_register_write(\
controller, \
unsolicited_frame_queue_control, \
value \
)
#define SCU_UFQPP_READ(controller) \
scu_sdma_register_read(\
controller, \
unsolicited_frame_put_pointer \
)
#define SCU_UFQPP_WRITE(controller, value) \
scu_sdma_register_write(\
controller, \
unsolicited_frame_put_pointer, \
value \
)
#define SCU_UFQGP_WRITE(controller, value) \
scu_sdma_register_write(\
controller, \
unsolicited_frame_get_pointer, \
value \
)
#define SCU_PDMACR_READ(controller) \
scu_sdma_register_read(\
controller, \
pdma_configuration \
)
#define SCU_PDMACR_WRITE(controller, value) \
scu_sdma_register_write(\
controller, \
pdma_configuration, \
value \
)
#define SCU_CDMACR_READ(controller) \
scu_sdma_register_read(\
controller, \
cdma_configuration \
)
#define SCU_CDMACR_WRITE(controller, value) \
scu_sdma_register_write(\
controller, \
cdma_configuration, \
value \
)
/*
* *****************************************************************************
* * SCU Port Task Scheduler Group Registers
* ***************************************************************************** */
/**
* scu_ptsg_register_read() -
*
* SCU_PTSG_REGISTER_ACCESS_MACROS
*/
#define scu_ptsg_register_read(controller, reg) \
scu_register_read(\
(controller), \
(controller)->scu_registers->peg0.ptsg.reg \
)
#define scu_ptsg_register_write(controller, reg, value) \
scu_register_write(\
(controller), \
(controller)->scu_registers->peg0.ptsg.reg, \
(value) \
)
/**
* SCU_PTSGCR_READ() -
*
* SCU_PTSG_REGISTERS
*/
#define SCU_PTSGCR_READ(controller) \
scu_ptsg_register_read(\
(controller), \
control \
)
#define SCU_PTSGCR_WRITE(controller, value) \
scu_ptsg_register_write(\
(controller), \
control, \
value \
)
#define SCU_PTSGRTC_READ(controller) \
scu_ptsg_register_read(\
contoller, \
real_time_clock \
)
#endif /* _SCIC_SDS_CONTROLLER_REGISTERS_H_ */

View File

@ -0,0 +1,95 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_PCI_H_
#define _SCIC_SDS_PCI_H_
/**
* This file contains the prototypes/macros utilized in writing out PCI data
* for the SCI core.
*
*
*/
#include <asm/io.h>
#include "sci_types.h"
struct scic_sds_controller;
void scic_sds_pci_bar_initialization(struct scic_sds_controller *scic);
/* for debug we separate scu and smu accesses and require a controller */
static inline u32 scic_sds_pci_read_smu_dword(struct scic_sds_controller *scic, void __iomem *addr)
{
return readl(addr);
}
static inline void scic_sds_pci_write_smu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value)
{
writel(value, addr);
}
static inline u32 scic_sds_pci_read_scu_dword(struct scic_sds_controller *scic, void __iomem *addr)
{
return readl(addr);
}
static inline void scic_sds_pci_write_scu_dword(struct scic_sds_controller *scic, void __iomem *addr, u32 value)
{
writel(value, addr);
}
#endif /* _SCIC_SDS_PCI_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,491 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_PHY_H_
#define _SCIC_SDS_PHY_H_
/**
* This file contains the structures, constants and prototypes for the
* struct scic_sds_phy object.
*
*
*/
#include "intel_sata.h"
#include "intel_sas.h"
#include "sci_base_phy.h"
#include "scu_registers.h"
struct scic_sds_port;
/**
*
*
* This is the timeout value for the SATA phy to wait for a SIGNATURE FIS
* before restarting the starting state machine. Technically, the old parallel
* ATA specification required up to 30 seconds for a device to issue its
* signature FIS as a result of a soft reset. Now we see that devices respond
* generally within 15 seconds, but we'll use 25 for now.
*/
#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT 25000
/**
*
*
* This is the timeout for the SATA OOB/SN because the hardware does not
* recognize a hot plug after OOB signal but before the SN signals. We need to
* make sure after a hotplug timeout if we have not received the speed event
* notification from the hardware that we restart the hardware OOB state
* machine.
*/
#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250
/**
* enum SCIC_SDS_PHY_STARTING_SUBSTATES -
*
*
*/
enum SCIC_SDS_PHY_STARTING_SUBSTATES {
/**
* Initial state
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_INITIAL,
/**
* Wait state for the hardware OSSP event type notification
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_OSSP_EN,
/**
* Wait state for the PHY speed notification
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_SPEED_EN,
/**
* Wait state for the IAF Unsolicited frame notification
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_IAF_UF,
/**
* Wait state for the request to consume power
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SAS_POWER,
/**
* Wait state for request to consume power
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_POWER,
/**
* Wait state for the SATA PHY notification
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_PHY_EN,
/**
* Wait for the SATA PHY speed notification
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SATA_SPEED_EN,
/**
* Wait state for the SIGNATURE FIS unsolicited frame notification
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_AWAIT_SIG_FIS_UF,
/**
* Exit state for this state machine
*/
SCIC_SDS_PHY_STARTING_SUBSTATE_FINAL,
/**
* Maximum number of substates for the STARTING state machine
*/
SCIC_SDS_PHY_STARTING_MAX_SUBSTATES
};
struct scic_sds_port;
struct scic_sds_controller;
#ifdef SCIC_DEBUG_ENABLED
#define MAX_STATE_TRANSITION_RECORD (256)
/**
*
*
* Debug code to record the state transitions for the phy object
*/
struct scic_sds_phy_state_record {
struct sci_base_observer base_state_observer;
struct sci_base_observer starting_state_observer;
u16 index;
u32 state_transition_table[MAX_STATE_TRANSITION_RECORD];
};
#endif /* SCIC_DEBUG_ENABLED */
/**
* This enumeration provides a named phy type for the state machine
*
*
*/
enum SCIC_SDS_PHY_PROTOCOL {
/**
* This is an unknown phy type since there is either nothing on the other
* end or we have not detected the phy type as yet.
*/
SCIC_SDS_PHY_PROTOCOL_UNKNOWN,
/**
* This is a SAS PHY
*/
SCIC_SDS_PHY_PROTOCOL_SAS,
/**
* This is a SATA PHY
*/
SCIC_SDS_PHY_PROTOCOL_SATA,
SCIC_SDS_MAX_PHY_PROTOCOLS
};
/**
* struct scic_sds_phy - This structure contains or references all of the data
* necessary to represent the core phy object and SCU harware protocol
* engine.
*
*
*/
struct scic_sds_phy {
struct sci_base_phy parent;
/**
* This field specifies the port object that owns/contains this phy.
*/
struct scic_sds_port *owning_port;
/**
* This field indicates whether the phy supports 1.5 Gb/s, 3.0 Gb/s,
* or 6.0 Gb/s operation.
*/
enum sci_sas_link_rate max_negotiated_speed;
/**
* This member specifies the protocol being utilized on this phy. This
* field contains a legitamite value once the PHY has link trained with
* a remote phy.
*/
enum SCIC_SDS_PHY_PROTOCOL protocol;
/**
* This field specifies the index with which this phy is associated (0-3).
*/
u8 phy_index;
/**
* This member indicates if this particular PHY has received a BCN while
* it had no port assignement. This BCN will be reported once the phy is
* assigned to a port.
*/
bool bcn_received_while_port_unassigned;
/**
* This field indicates if this PHY is currently in the process of
* link training (i.e. it has started OOB, but has yet to perform
* IAF exchange/Signature FIS reception).
*/
bool is_in_link_training;
union {
struct {
struct sci_sas_identify_address_frame identify_address_frame_buffer;
} sas;
struct {
struct sata_fis_reg_d2h signature_fis_buffer;
} sata;
} phy_type;
/**
* This field contains a reference to the timer utilized in detecting
* when a signature FIS timeout has occurred. The signature FIS is the
* first FIS sent by an attached SATA device after OOB/SN.
*/
void *sata_timeout_timer;
struct scic_sds_phy_state_handler *state_handlers;
struct sci_base_state_machine starting_substate_machine;
#ifdef SCIC_DEBUG_ENABLED
struct scic_sds_phy_state_record state_record;
#endif /* SCIC_DEBUG_ENABLED */
/**
* This field points to the link layer register set within the SCU.
*/
struct scu_link_layer_registers *link_layer_registers;
};
typedef enum sci_status (*SCIC_SDS_PHY_EVENT_HANDLER_T)(struct scic_sds_phy *, u32);
typedef enum sci_status (*SCIC_SDS_PHY_FRAME_HANDLER_T)(struct scic_sds_phy *, u32);
typedef enum sci_status (*SCIC_SDS_PHY_POWER_HANDLER_T)(struct scic_sds_phy *);
/**
* struct scic_sds_phy_state_handler -
*
*
*/
struct scic_sds_phy_state_handler {
/**
* This is the struct sci_base_phy object state handlers.
*/
struct sci_base_phy_state_handler parent;
/**
* The state handler for unsolicited frames received from the SCU hardware.
*/
SCIC_SDS_PHY_FRAME_HANDLER_T frame_handler;
/**
* The state handler for events received from the SCU hardware.
*/
SCIC_SDS_PHY_EVENT_HANDLER_T event_handler;
/**
* The state handler for staggered spinup.
*/
SCIC_SDS_PHY_POWER_HANDLER_T consume_power_handler;
};
extern struct scic_sds_phy_state_handler scic_sds_phy_state_handler_table[];
extern const struct sci_base_state scic_sds_phy_state_table[];
extern const struct sci_base_state scic_sds_phy_starting_substates[];
extern struct scic_sds_phy_state_handler
scic_sds_phy_starting_substate_handler_table[];
/**
* scic_sds_phy_get_index() -
*
* This macro returns the phy index for the specified phy
*/
#define scic_sds_phy_get_index(phy) \
((phy)->phy_index)
/**
* scic_sds_phy_get_controller() - This macro returns the controller for this
* phy
*
*
*/
#define scic_sds_phy_get_controller(phy) \
(scic_sds_port_get_controller((phy)->owning_port))
/**
* scic_sds_phy_get_base_state_machine() - This macro returns the state machine
* for the base phy
*
*
*/
#define scic_sds_phy_get_base_state_machine(phy) \
(&(phy)->parent.state_machine)
/**
* scic_sds_phy_get_starting_substate_machine() - This macro returns the
* starting substate machine for this phy
*
*
*/
#define scic_sds_phy_get_starting_substate_machine(phy) \
(&(phy)->starting_substate_machine)
/**
* scic_sds_phy_set_state_handlers() - This macro sets the state handlers for
* this phy object
*
*
*/
#define scic_sds_phy_set_state_handlers(phy, handlers) \
((phy)->state_handlers = (handlers))
/**
* scic_sds_phy_set_base_state_handlers() -
*
* This macro set the base state handlers for the phy object.
*/
#define scic_sds_phy_set_base_state_handlers(phy, state_id) \
scic_sds_phy_set_state_handlers(\
(phy), \
&scic_sds_phy_state_handler_table[(state_id)] \
)
/**
* scic_sds_phy_is_ready() -
*
* This macro returns true if the current base state for this phy is
* SCI_BASE_PHY_STATE_READY
*/
#define scic_sds_phy_is_ready(phy) \
(\
SCI_BASE_PHY_STATE_READY \
== sci_base_state_machine_get_state(\
scic_sds_phy_get_base_state_machine(phy) \
) \
)
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
void scic_sds_phy_construct(
struct scic_sds_phy *this_phy,
struct scic_sds_port *owning_port,
u8 phy_index);
struct scic_sds_port *scic_sds_phy_get_port(
struct scic_sds_phy *this_phy);
void scic_sds_phy_set_port(
struct scic_sds_phy *this_phy,
struct scic_sds_port *owning_port);
enum sci_status scic_sds_phy_initialize(
struct scic_sds_phy *this_phy,
struct scu_link_layer_registers *link_layer_registers);
enum sci_status scic_sds_phy_start(
struct scic_sds_phy *this_phy);
enum sci_status scic_sds_phy_stop(
struct scic_sds_phy *this_phy);
enum sci_status scic_sds_phy_reset(
struct scic_sds_phy *this_phy);
/* --------------------------------------------------------------------------- */
void scic_sds_phy_suspend(
struct scic_sds_phy *this_phy);
void scic_sds_phy_resume(
struct scic_sds_phy *this_phy);
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_phy_event_handler(
struct scic_sds_phy *this_phy,
u32 event_code);
enum sci_status scic_sds_phy_frame_handler(
struct scic_sds_phy *this_phy,
u32 frame_index);
enum sci_status scic_sds_phy_consume_power_handler(
struct scic_sds_phy *this_phy);
void scic_sds_phy_get_sas_address(
struct scic_sds_phy *this_phy,
struct sci_sas_address *sas_address);
void scic_sds_phy_get_attached_sas_address(
struct scic_sds_phy *this_phy,
struct sci_sas_address *sas_address);
void scic_sds_phy_get_protocols(
struct scic_sds_phy *this_phy,
struct sci_sas_identify_address_frame_protocols *protocols);
void scic_sds_phy_get_attached_phy_protocols(
struct scic_sds_phy *this_phy,
struct sci_sas_identify_address_frame_protocols *protocols);
/*
* ****************************************************************************-
* * SCIC SDS PHY Handler Methods
* ****************************************************************************- */
enum sci_status scic_sds_phy_default_start_handler(
struct sci_base_phy *phy);
enum sci_status scic_sds_phy_default_stop_handler(
struct sci_base_phy *phy);
enum sci_status scic_sds_phy_default_reset_handler(
struct sci_base_phy *phy);
enum sci_status scic_sds_phy_default_destroy_handler(
struct sci_base_phy *phy);
enum sci_status scic_sds_phy_default_frame_handler(
struct scic_sds_phy *phy,
u32 frame_index);
enum sci_status scic_sds_phy_default_event_handler(
struct scic_sds_phy *phy,
u32 evnet_code);
enum sci_status scic_sds_phy_default_consume_power_handler(
struct scic_sds_phy *phy);
#endif /* _SCIC_SDS_PHY_H_ */

View File

@ -0,0 +1,187 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_PHY_REGISTERS_H_
#define _SCIC_SDS_PHY_REGISTERS_H_
/**
* This file contains the macros used by the phy object to read/write to the
* SCU link layer registers.
*
*
*/
#include "scic_sds_controller.h"
/*
* *****************************************************************************
* * SCU LINK LAYER REGISTER OPERATIONS
* ***************************************************************************** */
/**
* scu_link_layer_register_read() -
*
* THis macro requests the SCU register write for the specified link layer
* register.
*/
#define scu_link_layer_register_read(phy, reg) \
scu_register_read(\
scic_sds_phy_get_controller(phy), \
(phy)->link_layer_registers->reg \
)
/**
* scu_link_layer_register_write() -
*
* This macro requests the SCU register read for the specified link layer
* register.
*/
#define scu_link_layer_register_write(phy, reg, value) \
scu_register_write(\
scic_sds_phy_get_controller(phy), \
(phy)->link_layer_registers->reg, \
(value) \
)
/*
* *****************************************************************************
* * SCU LINK LAYER REGISTERS
* ***************************************************************************** */
/* / This macro reads from the SAS Identify Frame PHY Identifier register */
#define SCU_SAS_TIPID_READ(phy) \
scu_link_layer_register_read(phy, identify_frame_phy_id)
/* / This macro writes to the SAS Identify Frame PHY Identifier register */
#define SCU_SAS_TIPID_WRITE(phy, value) \
scu_link_layer_register_write(phy, identify_frame_phy_id, value)
/* / This macro reads from the SAS Identification register */
#define SCU_SAS_TIID_READ(phy) \
scu_link_layer_register_read(phy, transmit_identification)
/* / This macro writes to the SAS Identification register */
#define SCU_SAS_TIID_WRITE(phy, value) \
scu_link_layer_register_write(phy, transmit_identification, value)
/* / This macro reads the SAS Device Name High register */
#define SCU_SAS_TIDNH_READ(phy) \
scu_link_layer_register_read(phy, sas_device_name_high)
/* / This macro writes the SAS Device Name High register */
#define SCU_SAS_TIDNH_WRITE(phy, value) \
scu_link_layer_register_write(phy, sas_device_name_high, value)
/* / This macro reads the SAS Device Name Low register */
#define SCU_SAS_TIDNL_READ(phy) \
scu_link_layer_register_read(phy, sas_device_name_low)
/* / This macro writes the SAS Device Name Low register */
#define SCU_SAS_TIDNL_WRITE(phy, value) \
scu_link_layer_register_write(phy, sas_device_name_low, value)
/* / This macro reads the Source SAS Address High register */
#define SCU_SAS_TISSAH_READ(phy) \
scu_link_layer_register_read(phy, source_sas_address_high)
/* / This macro writes the Source SAS Address High register */
#define SCU_SAS_TISSAH_WRITE(phy, value) \
scu_link_layer_register_write(phy, source_sas_address_high, value)
/* / This macro reads the Source SAS Address Low register */
#define SCU_SAS_TISSAL_READ(phy) \
scu_link_layer_register_read(phy, source_sas_address_low)
/* / This macro writes the Source SAS Address Low register */
#define SCU_SAS_TISSAL_WRITE(phy, value) \
scu_link_layer_register_write(phy, source_sas_address_low, value)
/* / This macro reads the PHY Configuration register */
#define SCU_SAS_PCFG_READ(phy) \
scu_link_layer_register_read(phy, phy_configuration);
/* / This macro writes the PHY Configuration register */
#define SCU_SAS_PCFG_WRITE(phy, value) \
scu_link_layer_register_write(phy, phy_configuration, value)
/* / This macro reads the PHY Enable Spinup register */
#define SCU_SAS_ENSPINUP_READ(phy) \
scu_link_layer_register_read(phy, notify_enable_spinup_control)
/* / This macro writes the PHY Enable Spinup register */
#define SCU_SAS_ENSPINUP_WRITE(phy, value) \
scu_link_layer_register_write(phy, notify_enable_spinup_control, value)
/* / This macro reads the PHY Capacity register */
#define SCU_SAS_PHYCAP_READ(phy) \
scu_link_layer_register_read(phy, phy_capabilities)
/* / This macro writes the PHY Capacity register */
#define SCU_SAS_PHYCAP_WRITE(phy, value) \
scu_link_layer_register_write(phy, phy_capabilities, value)
/* / This macro reads the Recieved PHY Capacity register */
#define SCU_SAS_RECPHYCAP_READ(phy) \
scu_link_layer_register_read(phy, receive_phycap)
/* / This macro reads the link layer control register */
#define SCU_SAS_LLCTL_READ(phy) \
scu_link_layer_register_read(phy, link_layer_control);
/* / This macro writes the link layer control register */
#define SCU_SAS_LLCTL_WRITE(phy, value) \
scu_link_layer_register_write(phy, link_layer_control, value);
#endif /* _SCIC_SDS_PHY_REGISTERS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,514 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_PORT_H_
#define _SCIC_SDS_PORT_H_
/**
* This file contains the structures, constants and prototypes for the
* struct scic_sds_port object.
*
*
*/
#include "sci_controller_constants.h"
#include "intel_sas.h"
#include "sci_base_port.h"
#include "sci_base_phy.h"
#include "scu_registers.h"
#define SCIC_SDS_DUMMY_PORT 0xFF
/**
* enum SCIC_SDS_PORT_READY_SUBSTATES -
*
* This enumeration depicts all of the states for the core port ready substate
* machine.
*/
enum SCIC_SDS_PORT_READY_SUBSTATES {
/**
* The substate where the port is started and ready but has no active phys.
*/
SCIC_SDS_PORT_READY_SUBSTATE_WAITING,
/**
* The substate where the port is started and ready and there is at least one
* phy operational.
*/
SCIC_SDS_PORT_READY_SUBSTATE_OPERATIONAL,
/**
* The substate where the port is started and there was an add/remove phy
* event. This state is only used in Automatic Port Configuration Mode (APC)
*/
SCIC_SDS_PORT_READY_SUBSTATE_CONFIGURING,
SCIC_SDS_PORT_READY_MAX_SUBSTATES
};
struct scic_sds_controller;
struct scic_sds_phy;
struct scic_sds_remote_device;
struct scic_sds_request;
/**
* struct scic_sds_port -
*
* The core port object provides the the abstraction for an SCU port.
*/
struct scic_sds_port {
/**
* This field is the oommon base port object.
*/
struct sci_base_port parent;
/**
* This field is the port index that is reported to the SCI USER. This allows
* the actual hardware physical port to change without the SCI USER getting a
* different answer for the get port index.
*/
u8 logical_port_index;
/**
* This field is the port index used to program the SCU hardware.
*/
u8 physical_port_index;
/**
* This field contains the active phy mask for the port. This mask is used in
* conjunction with the phy state to determine which phy to select for some
* port operations.
*/
u8 active_phy_mask;
/**
* This field contains the count of the io requests started on this port
* object. It is used to control controller shutdown.
*/
u32 started_request_count;
/**
* This field contains the number of devices assigned to this port. It is
* used to control port start requests.
*/
u32 assigned_device_count;
/**
* This field contains the reason for the port not going ready. It is
* assigned in the state handlers and used in the state transition.
*/
u32 not_ready_reason;
/**
* This field is the table of phys assigned to the port.
*/
struct scic_sds_phy *phy_table[SCI_MAX_PHYS];
/**
* This field is a pointer back to the controller that owns this port object.
*/
struct scic_sds_controller *owning_controller;
/**
* This field contains the port start/stop timer handle.
*/
void *timer_handle;
/**
* This field points to the current set of state handlers for this port
* object. These state handlers are assigned at each enter state of the state
* machine.
*/
struct scic_sds_port_state_handler *state_handlers;
/**
* This field is the ready substate machine for the port.
*/
struct sci_base_state_machine ready_substate_machine;
/* / Memory mapped hardware register space */
/**
* This field is the pointer to the transport layer register for the SCU
* hardware.
*/
struct scu_transport_layer_registers *transport_layer_registers;
/**
* This field is the pointer to the port task scheduler registers for the SCU
* hardware.
*/
struct scu_port_task_scheduler_registers *port_task_scheduler_registers;
/**
* This field is identical for all port objects and points to the port task
* scheduler group PE configuration registers. It is used to assign PEs to a
* port.
*/
SCU_PORT_PE_CONFIGURATION_REGISTER_T *port_pe_configuration_register;
/**
* This field is the VIIT register space for ths port object.
*/
struct scu_viit_entry *viit_registers;
};
typedef enum sci_status (*SCIC_SDS_PORT_EVENT_HANDLER_T)(struct scic_sds_port *, u32);
typedef enum sci_status (*SCIC_SDS_PORT_FRAME_HANDLER_T)(struct scic_sds_port *, u32);
typedef void (*SCIC_SDS_PORT_LINK_HANDLER_T)(struct scic_sds_port *, struct scic_sds_phy *);
typedef enum sci_status (*SCIC_SDS_PORT_IO_REQUEST_HANDLER_T)(
struct scic_sds_port *,
struct scic_sds_remote_device *,
struct scic_sds_request *);
struct scic_sds_port_state_handler {
struct sci_base_port_state_handler parent;
SCIC_SDS_PORT_FRAME_HANDLER_T frame_handler;
SCIC_SDS_PORT_EVENT_HANDLER_T event_handler;
SCIC_SDS_PORT_LINK_HANDLER_T link_up_handler;
SCIC_SDS_PORT_LINK_HANDLER_T link_down_handler;
SCIC_SDS_PORT_IO_REQUEST_HANDLER_T start_io_handler;
SCIC_SDS_PORT_IO_REQUEST_HANDLER_T complete_io_handler;
};
extern const struct sci_base_state scic_sds_port_state_table[];
extern const struct sci_base_state scic_sds_port_ready_substate_table[];
extern struct scic_sds_port_state_handler scic_sds_port_state_handler_table[];
extern struct scic_sds_port_state_handler scic_sds_port_ready_substate_handler_table[];
/**
* scic_sds_port_get_controller() -
*
* Helper macro to get the owning controller of this port
*/
#define scic_sds_port_get_controller(this_port) \
((this_port)->owning_controller)
/**
* scic_sds_port_get_base_state_machine() -
*
* Helper macro to get the base state machine for this port
*/
#define scic_sds_port_get_base_state_machine(this_port) \
(&(this_port)->parent.state_machine)
/**
* scic_sds_port_set_base_state_handlers() -
*
* This macro will change the state handlers to those of the specified state id
*/
#define scic_sds_port_set_base_state_handlers(this_port, state_id) \
scic_sds_port_set_state_handlers(\
(this_port), &scic_sds_port_state_handler_table[(state_id)])
/**
* scic_sds_port_get_ready_substate_machine() -
*
* Helper macro to get the ready substate machine for this port
*/
#define scic_sds_port_get_ready_substate_machine(this_port) \
(&(this_port)->ready_substate_machine)
/**
* scic_sds_port_set_state_handlers() -
*
* Helper macro to set the port object state handlers
*/
#define scic_sds_port_set_state_handlers(this_port, handlers) \
((this_port)->state_handlers = (handlers))
/**
* scic_sds_port_get_index() -
*
* This macro returns the physical port index for this port object
*/
#define scic_sds_port_get_index(this_port) \
((this_port)->physical_port_index)
/**
* scic_sds_port_increment_request_count() -
*
* Helper macro to increment the started request count
*/
#define scic_sds_port_increment_request_count(this_port) \
((this_port)->started_request_count++)
#ifdef SCIC_DEBUG_ENABLED
/**
* scic_sds_port_decrement_request_count() - This method decrements the started
* io request count. The method will not decrment the started io request
* count below 0 and will log a debug message if this is attempted.
*
*
*/
void scic_sds_port_decrement_request_count(
struct scic_sds_port *this_port);
#else
/**
* scic_sds_port_decrement_request_count() -
*
* Helper macro to decrement the started io request count. The macro will not
* decrement the started io request count below 0.
*/
#define scic_sds_port_decrement_request_count(this_port) \
(\
(this_port)->started_request_count = (\
((this_port)->started_request_count == 0) ? \
(this_port)->started_request_count : \
((this_port)->started_request_count - 1) \
) \
)
#endif
/**
* scic_sds_port_write_phy_assignment() -
*
* Helper macro to write the phys port assignment
*/
#define scic_sds_port_write_phy_assignment(port, phy) \
SCU_PCSPExCR_WRITE(\
(port), \
(phy)->phy_index, \
(port)->physical_port_index \
)
/**
* scic_sds_port_read_phy_assignment() -
*
* Helper macro to read the phys port assignment
*/
#define scic_sds_port_read_phy_assignment(port, phy) \
SCU_PCSPExCR_READ(\
(port), \
(phy)->phy_index \
)
#define scic_sds_port_active_phy(port, phy) \
(((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0)
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
void scic_sds_port_construct(
struct scic_sds_port *this_port,
u8 port_index,
struct scic_sds_controller *owning_controller);
enum sci_status scic_sds_port_initialize(
struct scic_sds_port *this_port,
void *transport_layer_registers,
void *port_task_scheduler_registers,
void *port_configuration_regsiter,
void *viit_registers);
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_port_add_phy(
struct scic_sds_port *this_port,
struct scic_sds_phy *the_phy);
enum sci_status scic_sds_port_remove_phy(
struct scic_sds_port *this_port,
struct scic_sds_phy *the_phy);
void scic_sds_port_set_direct_attached_device_id(
struct scic_sds_port *this_port,
u32 device_id);
void scic_sds_port_activate_phy(
struct scic_sds_port *this_port,
struct scic_sds_phy *phy,
bool do_notify_user);
void scic_sds_port_deactivate_phy(
struct scic_sds_port *this_port,
struct scic_sds_phy *phy,
bool do_notify_user);
void scic_sds_port_general_link_up_handler(
struct scic_sds_port *this_port,
struct scic_sds_phy *the_phy,
bool do_notify_user);
bool scic_sds_port_link_detected(
struct scic_sds_port *this_port,
struct scic_sds_phy *phy);
void scic_sds_port_link_up(
struct scic_sds_port *this_port,
struct scic_sds_phy *phy);
void scic_sds_port_link_down(
struct scic_sds_port *this_port,
struct scic_sds_phy *phy);
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_port_start_io(
struct scic_sds_port *this_port,
struct scic_sds_remote_device *the_device,
struct scic_sds_request *the_io_request);
enum sci_status scic_sds_port_complete_io(
struct scic_sds_port *this_port,
struct scic_sds_remote_device *the_device,
struct scic_sds_request *the_io_request);
/* --------------------------------------------------------------------------- */
void scic_sds_port_update_viit_entry(
struct scic_sds_port *this_port);
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_port_default_start_handler(
struct sci_base_port *port);
enum sci_status scic_sds_port_default_destruct_handler(
struct sci_base_port *port);
enum sci_status scic_sds_port_default_reset_handler(
struct sci_base_port *port,
u32 timeout);
enum sci_status scic_sds_port_default_remove_phy_handler(
struct sci_base_port *port,
struct sci_base_phy *phy);
enum sci_status scic_sds_port_default_frame_handler(
struct scic_sds_port *port,
u32 frame_index);
enum sci_status scic_sds_port_default_event_handler(
struct scic_sds_port *port,
u32 event_code);
void scic_sds_port_default_link_up_handler(
struct scic_sds_port *this_port,
struct scic_sds_phy *phy);
void scic_sds_port_default_link_down_handler(
struct scic_sds_port *this_port,
struct scic_sds_phy *phy);
enum sci_status scic_sds_port_default_start_io_handler(
struct scic_sds_port *port,
struct scic_sds_remote_device *device,
struct scic_sds_request *io_request);
enum sci_sas_link_rate scic_sds_port_get_max_allowed_speed(
struct scic_sds_port *this_port);
void scic_sds_port_broadcast_change_received(
struct scic_sds_port *this_port,
struct scic_sds_phy *this_phy);
bool scic_sds_port_is_valid_phy_assignment(
struct scic_sds_port *this_port,
u32 phy_index);
bool scic_sds_port_is_phy_mask_valid(
struct scic_sds_port *this_port,
u32 phy_mask);
u32 scic_sds_port_get_phys(
struct scic_sds_port *this_port);
void scic_sds_port_get_sas_address(
struct scic_sds_port *this_port,
struct sci_sas_address *sas_address);
void scic_sds_port_get_attached_sas_address(
struct scic_sds_port *this_port,
struct sci_sas_address *sas_address);
void scic_sds_port_get_attached_protocols(
struct scic_sds_port *this_port,
struct sci_sas_identify_address_frame_protocols *protocols);
enum sci_status scic_sds_port_set_phy(
struct scic_sds_port *port,
struct scic_sds_phy *phy);
enum sci_status scic_sds_port_clear_phy(
struct scic_sds_port *port,
struct scic_sds_phy *phy);
#endif /* _SCIC_SDS_PORT_H_ */

View File

@ -0,0 +1,851 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the implementation for the public and protected methods
* for the port configuration agent.
*
*
*/
#include "sci_environment.h"
#include "scic_controller.h"
#include "scic_sds_controller.h"
#include "scic_sds_port_configuration_agent.h"
#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10)
#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10)
#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100)
enum SCIC_SDS_APC_ACTIVITY {
SCIC_SDS_APC_SKIP_PHY,
SCIC_SDS_APC_ADD_PHY,
SCIC_SDS_APC_START_TIMER,
SCIC_SDS_APC_ACTIVITY_MAX
};
/*
* ******************************************************************************
* General port configuration agent routines
* ****************************************************************************** */
/**
*
* @address_one: A SAS Address to be compared.
* @address_two: A SAS Address to be compared.
*
* Compare the two SAS Address and if SAS Address One is greater than SAS
* Address Two then return > 0 else if SAS Address One is less than SAS Address
* Two return < 0 Otherwise they are the same return 0 A signed value of x > 0
* > y where x is returned for Address One > Address Two y is returned for
* Address One < Address Two 0 is returned ofr Address One = Address Two
*/
static s32 sci_sas_address_compare(
struct sci_sas_address address_one,
struct sci_sas_address address_two)
{
if (address_one.high > address_two.high) {
return 1;
} else if (address_one.high < address_two.high) {
return -1;
} else if (address_one.low > address_two.low) {
return 1;
} else if (address_one.low < address_two.low) {
return -1;
}
/* The two SAS Address must be identical */
return 0;
}
/**
*
* @controller: The controller object used for the port search.
* @phy: The phy object to match.
*
* This routine will find a matching port for the phy. This means that the
* port and phy both have the same broadcast sas address and same received sas
* address. The port address or the SCI_INVALID_HANDLE if there is no matching
* port. port address if the port can be found to match the phy.
* SCI_INVALID_HANDLE if there is no matching port for the phy.
*/
static struct scic_sds_port *scic_sds_port_configuration_agent_find_port(
struct scic_sds_controller *controller,
struct scic_sds_phy *phy)
{
u8 port_index;
struct scic_sds_port *port_handle;
struct sci_sas_address port_sas_address;
struct sci_sas_address port_attached_device_address;
struct sci_sas_address phy_sas_address;
struct sci_sas_address phy_attached_device_address;
/*
* Since this phy can be a member of a wide port check to see if one or
* more phys match the sent and received SAS address as this phy in which
* case it should participate in the same port. */
scic_sds_phy_get_sas_address(phy, &phy_sas_address);
scic_sds_phy_get_attached_sas_address(phy, &phy_attached_device_address);
for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
if (scic_controller_get_port_handle(controller, port_index, &port_handle) == SCI_SUCCESS) {
struct scic_sds_port *port = (struct scic_sds_port *)port_handle;
scic_sds_port_get_sas_address(port, &port_sas_address);
scic_sds_port_get_attached_sas_address(port, &port_attached_device_address);
if (
(sci_sas_address_compare(port_sas_address, phy_sas_address) == 0)
&& (sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0)
) {
return port;
}
}
}
return SCI_INVALID_HANDLE;
}
/**
*
* @controller: This is the controller object that contains the port agent
* @port_agent: This is the port configruation agent for the controller.
*
* This routine will validate the port configuration is correct for the SCU
* hardware. The SCU hardware allows for port configurations as follows. LP0
* -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2,
* PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for
* this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION
* the port configuration is not valid for this port configuration agent.
*/
static enum sci_status scic_sds_port_configuration_agent_validate_ports(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent)
{
struct sci_sas_address first_address;
struct sci_sas_address second_address;
/*
* Sanity check the max ranges for all the phys the max index
* is always equal to the port range index */
if (
(port_agent->phy_valid_port_range[0].max_index != 0)
|| (port_agent->phy_valid_port_range[1].max_index != 1)
|| (port_agent->phy_valid_port_range[2].max_index != 2)
|| (port_agent->phy_valid_port_range[3].max_index != 3)
) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
/*
* This is a request to configure a single x4 port or at least attempt
* to make all the phys into a single port */
if (
(port_agent->phy_valid_port_range[0].min_index == 0)
&& (port_agent->phy_valid_port_range[1].min_index == 0)
&& (port_agent->phy_valid_port_range[2].min_index == 0)
&& (port_agent->phy_valid_port_range[3].min_index == 0)
) {
return SCI_SUCCESS;
}
/*
* This is a degenerate case where phy 1 and phy 2 are assigned
* to the same port this is explicitly disallowed by the hardware
* unless they are part of the same x4 port and this condition was
* already checked above. */
if (port_agent->phy_valid_port_range[2].min_index == 1) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
/*
* PE0 and PE3 can never have the same SAS Address unless they
* are part of the same x4 wide port and we have already checked
* for this condition. */
scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
if (sci_sas_address_compare(first_address, second_address) == 0) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
/*
* PE0 and PE1 are configured into a 2x1 ports make sure that the
* SAS Address for PE0 and PE2 are different since they can not be
* part of the same port. */
if (
(port_agent->phy_valid_port_range[0].min_index == 0)
&& (port_agent->phy_valid_port_range[1].min_index == 1)
) {
scic_sds_phy_get_sas_address(&controller->phy_table[0], &first_address);
scic_sds_phy_get_sas_address(&controller->phy_table[2], &second_address);
if (sci_sas_address_compare(first_address, second_address) == 0) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
}
/*
* PE2 and PE3 are configured into a 2x1 ports make sure that the
* SAS Address for PE1 and PE3 are different since they can not be
* part of the same port. */
if (
(port_agent->phy_valid_port_range[2].min_index == 2)
&& (port_agent->phy_valid_port_range[3].min_index == 3)
) {
scic_sds_phy_get_sas_address(&controller->phy_table[1], &first_address);
scic_sds_phy_get_sas_address(&controller->phy_table[3], &second_address);
if (sci_sas_address_compare(first_address, second_address) == 0) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
}
return SCI_SUCCESS;
}
/*
* ******************************************************************************
* Manual port configuration agent routines
* ****************************************************************************** */
/**
*
*
* This routine will verify that all of the phys in the same port are using the
* same SAS address.
*/
static enum sci_status scic_sds_mpc_agent_validate_phy_configuration(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent)
{
u32 phy_mask;
u32 assigned_phy_mask;
struct sci_sas_address sas_address;
struct sci_sas_address phy_assigned_address;
u8 port_index;
u8 phy_index;
assigned_phy_mask = 0;
sas_address.high = 0;
sas_address.low = 0;
for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
phy_mask = controller->oem_parameters.sds1.ports[port_index].phy_mask;
if (phy_mask != 0) {
/*
* Make sure that one or more of the phys were not already assinged to
* a different port. */
if ((phy_mask & ~assigned_phy_mask) == 0) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
/* Find the starting phy index for this round through the loop */
for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
if ((1 << phy_index) & phy_mask) {
scic_sds_phy_get_sas_address(
&controller->phy_table[phy_index], &sas_address
);
/*
* The phy_index can be used as the starting point for the
* port range since the hardware starts all logical ports
* the same as the PE index. */
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
if (phy_index != port_index) {
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
break;
}
}
/*
* See how many additional phys are being added to this logical port.
* Note: We have not moved the current phy_index so we will actually
* compare the startting phy with itself.
* This is expected and required to add the phy to the port. */
while (phy_index < SCI_MAX_PHYS) {
if ((1 << phy_index) & phy_mask) {
scic_sds_phy_get_sas_address(
&controller->phy_table[phy_index], &phy_assigned_address
);
if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) {
/*
* The phy mask specified that this phy is part of the same port
* as the starting phy and it is not so fail this configuration */
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
}
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
scic_sds_port_add_phy(
&controller->port_table[port_index],
&controller->phy_table[phy_index]
);
assigned_phy_mask |= (1 << phy_index);
}
phy_index++;
}
}
}
return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
}
/**
*
*
* This timer routine is used to allow the SCI User to rediscover or change
* device objects before a new series of link up notifications because a link
* down has allowed a better port configuration.
*/
static void scic_sds_mpc_agent_timeout_handler(
void *object)
{
u8 index;
struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
struct scic_sds_port_configuration_agent *port_agent = &controller->port_agent;
u16 configure_phy_mask;
port_agent->timer_pending = false;
/* Find the mask of phys that are reported read but as yet unconfigured into a port */
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
for (index = 0; index < SCI_MAX_PHYS; index++) {
if (configure_phy_mask & (1 << index)) {
port_agent->link_up_handler(
controller,
port_agent,
scic_sds_phy_get_port(&controller->phy_table[index]),
&controller->phy_table[index]
);
}
}
}
/**
*
* @controller: This is the controller object that receives the link up
* notification.
* @port: This is the port object associated with the phy. If the is no
* associated port this is an SCI_INVALID_HANDLE.
* @phy: This is the phy object which has gone ready.
*
* This method handles the manual port configuration link up notifications.
* Since all ports and phys are associate at initialization time we just turn
* around and notifiy the port object that there is a link up. If this PHY is
* not associated with a port there is no action taken. Is it possible to get a
* link up notification from a phy that has no assocoated port?
*/
static void scic_sds_mpc_agent_link_up(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
/*
* If the port has an invalid handle then the phy was not assigned to
* a port. This is because the phy was not given the same SAS Address
* as the other PHYs in the port. */
if (port != SCI_INVALID_HANDLE) {
port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
scic_sds_port_link_up(port, phy);
if ((port->active_phy_mask & (1 << scic_sds_phy_get_index(phy))) != 0) {
port_agent->phy_configured_mask |= (1 << scic_sds_phy_get_index(phy));
}
}
}
/**
*
* @controller: This is the controller object that receives the link down
* notification.
* @port: This is the port object associated with the phy. If the is no
* associated port this is an SCI_INVALID_HANDLE. The port is an invalid
* handle only if the phy was never port of this port. This happens when
* the phy is not broadcasting the same SAS address as the other phys in the
* assigned port.
* @phy: This is the phy object which has gone link down.
*
* This method handles the manual port configuration link down notifications.
* Since all ports and phys are associated at initialization time we just turn
* around and notifiy the port object of the link down event. If this PHY is
* not associated with a port there is no action taken. Is it possible to get a
* link down notification from a phy that has no assocoated port?
*/
static void scic_sds_mpc_agent_link_down(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
if (port != SCI_INVALID_HANDLE) {
/*
* If we can form a new port from the remainder of the phys then we want
* to start the timer to allow the SCI User to cleanup old devices and
* rediscover the port before rebuilding the port with the phys that
* remain in the ready state. */
port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
port_agent->phy_configured_mask &= ~(1 << scic_sds_phy_get_index(phy));
/*
* Check to see if there are more phys waiting to be configured into a port.
* If there are allow the SCI User to tear down this port, if necessary, and
* then reconstruc the port after the timeout. */
if (
(port_agent->phy_configured_mask == 0x0000)
&& (port_agent->phy_ready_mask != 0x0000)
&& !port_agent->timer_pending
) {
port_agent->timer_pending = true;
scic_cb_timer_start(
controller,
port_agent->timer,
SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT
);
}
scic_sds_port_link_down(port, phy);
}
}
/*
* ******************************************************************************
* Automatic port configuration agent routines
* ****************************************************************************** */
/**
*
*
* This routine will verify that the phys are assigned a valid SAS address for
* automatic port configuration mode.
*/
static enum sci_status scic_sds_apc_agent_validate_phy_configuration(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent)
{
u8 phy_index;
u8 port_index;
struct sci_sas_address sas_address;
struct sci_sas_address phy_assigned_address;
phy_index = 0;
while (phy_index < SCI_MAX_PHYS) {
port_index = phy_index;
/* Get the assigned SAS Address for the first PHY on the controller. */
scic_sds_phy_get_sas_address(
&controller->phy_table[phy_index], &sas_address
);
while (++phy_index < SCI_MAX_PHYS) {
scic_sds_phy_get_sas_address(
&controller->phy_table[phy_index], &phy_assigned_address
);
/* Verify each of the SAS address are all the same for every PHY */
if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) {
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
} else {
port_agent->phy_valid_port_range[phy_index].min_index = phy_index;
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
break;
}
}
}
return scic_sds_port_configuration_agent_validate_ports(controller, port_agent);
}
/**
*
* @controller: This is the controller that to which the port agent is assigned.
* @port_agent: This is the port agent that is requesting the timer start
* operation.
* @phy: This is the phy that has caused the timer operation to be scheduled.
*
* This routine will restart the automatic port configuration timeout timer for
* the next time period. This could be caused by either a link down event or a
* link up event where we can not yet tell to which port a phy belongs.
*/
static void scic_sds_apc_agent_start_timer(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent,
struct scic_sds_phy *phy,
u32 timeout)
{
if (port_agent->timer_pending) {
scic_cb_timer_stop(controller, port_agent->timer);
}
port_agent->timer_pending = true;
scic_cb_timer_start(controller, port_agent->timer, timeout);
}
/**
*
* @controller: This is the controller object that receives the link up
* notification.
* @phy: This is the phy object which has gone link up.
*
* This method handles the automatic port configuration for link up
* notifications.
*/
static void scic_sds_apc_agent_configure_ports(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent,
struct scic_sds_phy *phy,
bool start_timer)
{
u8 port_index;
enum sci_status status;
struct scic_sds_port *port;
struct scic_sds_port *port_handle;
enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY;
port = scic_sds_port_configuration_agent_find_port(controller, phy);
if (port != SCI_INVALID_HANDLE) {
if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index))
apc_activity = SCIC_SDS_APC_ADD_PHY;
else
apc_activity = SCIC_SDS_APC_SKIP_PHY;
} else {
/*
* There is no matching Port for this PHY so lets search through the
* Ports and see if we can add the PHY to its own port or maybe start
* the timer and wait to see if a wider port can be made.
*
* Note the break when we reach the condition of the port id == phy id */
for (
port_index = port_agent->phy_valid_port_range[phy->phy_index].min_index;
port_index <= port_agent->phy_valid_port_range[phy->phy_index].max_index;
port_index++
) {
scic_controller_get_port_handle(controller, port_index, &port_handle);
port = (struct scic_sds_port *)port_handle;
/* First we must make sure that this PHY can be added to this Port. */
if (scic_sds_port_is_valid_phy_assignment(port, phy->phy_index)) {
/*
* Port contains a PHY with a greater PHY ID than the current
* PHY that has gone link up. This phy can not be part of any
* port so skip it and move on. */
if (port->active_phy_mask > (1 << phy->phy_index)) {
apc_activity = SCIC_SDS_APC_SKIP_PHY;
break;
}
/*
* We have reached the end of our Port list and have not found
* any reason why we should not either add the PHY to the port
* or wait for more phys to become active. */
if (port->physical_port_index == phy->phy_index) {
/*
* The Port either has no active PHYs.
* Consider that if the port had any active PHYs we would have
* or active PHYs with
* a lower PHY Id than this PHY. */
if (apc_activity != SCIC_SDS_APC_START_TIMER) {
apc_activity = SCIC_SDS_APC_ADD_PHY;
}
break;
}
/*
* The current Port has no active PHYs and this PHY could be part
* of this Port. Since we dont know as yet setup to start the
* timer and see if there is a better configuration. */
if (port->active_phy_mask == 0) {
apc_activity = SCIC_SDS_APC_START_TIMER;
}
} else if (port->active_phy_mask != 0) {
/*
* The Port has an active phy and the current Phy can not
* participate in this port so skip the PHY and see if
* there is a better configuration. */
apc_activity = SCIC_SDS_APC_SKIP_PHY;
}
}
}
/*
* Check to see if the start timer operations should instead map to an
* add phy operation. This is caused because we have been waiting to
* add a phy to a port but could not becuase the automatic port
* configuration engine had a choice of possible ports for the phy.
* Since we have gone through a timeout we are going to restrict the
* choice to the smallest possible port. */
if (
(start_timer == false)
&& (apc_activity == SCIC_SDS_APC_START_TIMER)
) {
apc_activity = SCIC_SDS_APC_ADD_PHY;
}
switch (apc_activity) {
case SCIC_SDS_APC_ADD_PHY:
status = scic_sds_port_add_phy(port, phy);
if (status == SCI_SUCCESS) {
port_agent->phy_configured_mask |= (1 << phy->phy_index);
}
break;
case SCIC_SDS_APC_START_TIMER:
scic_sds_apc_agent_start_timer(
controller, port_agent, phy, SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION
);
break;
case SCIC_SDS_APC_SKIP_PHY:
default:
/* do nothing the PHY can not be made part of a port at this time. */
break;
}
}
/**
*
* @controller: This is the controller object that receives the link up
* notification.
* @port: This is the port object associated with the phy. If the is no
* associated port this is an SCI_INVALID_HANDLE.
* @phy: This is the phy object which has gone link up.
*
* This method handles the automatic port configuration for link up
* notifications. Is it possible to get a link down notification from a phy
* that has no assocoated port?
*/
static void scic_sds_apc_agent_link_up(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
BUG_ON(port != SCI_INVALID_HANDLE);
port_agent->phy_ready_mask |= (1 << scic_sds_phy_get_index(phy));
scic_sds_apc_agent_configure_ports(controller, port_agent, phy, true);
}
/**
*
* @controller: This is the controller object that receives the link down
* notification.
* @port: This is the port object associated with the phy. If the is no
* associated port this is an SCI_INVALID_HANDLE.
* @phy: This is the phy object which has gone link down.
*
* This method handles the automatic port configuration link down
* notifications. not associated with a port there is no action taken. Is it
* possible to get a link down notification from a phy that has no assocoated
* port?
*/
static void scic_sds_apc_agent_link_down(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
port_agent->phy_ready_mask &= ~(1 << scic_sds_phy_get_index(phy));
if (port != SCI_INVALID_HANDLE) {
if (port_agent->phy_configured_mask & (1 << phy->phy_index)) {
enum sci_status status;
status = scic_sds_port_remove_phy(port, phy);
if (status == SCI_SUCCESS) {
port_agent->phy_configured_mask &= ~(1 << phy->phy_index);
}
}
}
}
/**
*
*
* This routine will try to configure the phys into ports when the timer fires.
*/
static void scic_sds_apc_agent_timeout_handler(
void *object)
{
u32 index;
struct scic_sds_port_configuration_agent *port_agent;
struct scic_sds_controller *controller = (struct scic_sds_controller *)object;
u16 configure_phy_mask;
port_agent = scic_sds_controller_get_port_configuration_agent(controller);
port_agent->timer_pending = false;
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
if (configure_phy_mask != 0x00) {
for (index = 0; index < SCI_MAX_PHYS; index++) {
if (configure_phy_mask & (1 << index)) {
scic_sds_apc_agent_configure_ports(
controller, port_agent, &controller->phy_table[index], false
);
}
}
}
}
/*
* ******************************************************************************
* Public port configuration agent routines
* ****************************************************************************** */
/**
*
*
* This method will construct the port configuration agent for operation. This
* call is universal for both manual port configuration and automatic port
* configuration modes.
*/
void scic_sds_port_configuration_agent_construct(
struct scic_sds_port_configuration_agent *port_agent)
{
u32 index;
port_agent->phy_configured_mask = 0x00;
port_agent->phy_ready_mask = 0x00;
port_agent->link_up_handler = NULL;
port_agent->link_down_handler = NULL;
port_agent->timer_pending = false;
port_agent->timer = NULL;
for (index = 0; index < SCI_MAX_PORTS; index++) {
port_agent->phy_valid_port_range[index].min_index = 0;
port_agent->phy_valid_port_range[index].max_index = 0;
}
}
/**
*
* @controller: This is the controller object for which the port agent is being
* initialized.
*
* This method will construct the port configuration agent for this controller.
*/
enum sci_status scic_sds_port_configuration_agent_initialize(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent)
{
enum sci_status status = SCI_SUCCESS;
enum SCIC_PORT_CONFIGURATION_MODE mode;
mode = scic_sds_controller_get_port_configuration_mode(controller);
if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
status = scic_sds_mpc_agent_validate_phy_configuration(controller, port_agent);
port_agent->link_up_handler = scic_sds_mpc_agent_link_up;
port_agent->link_down_handler = scic_sds_mpc_agent_link_down;
port_agent->timer = scic_cb_timer_create(
controller,
scic_sds_mpc_agent_timeout_handler,
controller
);
} else {
status = scic_sds_apc_agent_validate_phy_configuration(controller, port_agent);
port_agent->link_up_handler = scic_sds_apc_agent_link_up;
port_agent->link_down_handler = scic_sds_apc_agent_link_down;
port_agent->timer = scic_cb_timer_create(
controller,
scic_sds_apc_agent_timeout_handler,
controller
);
}
/* Make sure we have actually gotten a timer */
if ((status == SCI_SUCCESS) && (port_agent->timer == NULL)) {
dev_err(scic_to_dev(controller),
"%s: Controller 0x%p automatic port configuration "
"agent could not get timer.\n",
__func__,
controller);
status = SCI_FAILURE;
}
return status;
}

View File

@ -0,0 +1,108 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
#define _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_
/**
* This file contains the structures, constants and prototypes used for the
* core controller automatic port configuration engine.
*
*
*/
#include "scic_sds_port.h"
#include "scic_sds_phy.h"
struct scic_sds_controller;
struct scic_sds_port_configuration_agent;
struct scic_sds_port;
struct scic_sds_phy;
typedef void (*SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T)(
struct scic_sds_controller *,
struct scic_sds_port_configuration_agent *,
struct scic_sds_port *,
struct scic_sds_phy *
);
struct SCIC_SDS_PORT_RANGE {
u8 min_index;
u8 max_index;
};
struct scic_sds_port_configuration_agent {
u16 phy_configured_mask;
u16 phy_ready_mask;
struct SCIC_SDS_PORT_RANGE phy_valid_port_range[SCI_MAX_PHYS];
bool timer_pending;
SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_up_handler;
SCIC_SDS_PORT_CONFIGURATION_AGENT_PHY_HANDLER_T link_down_handler;
void *timer;
};
void scic_sds_port_configuration_agent_construct(
struct scic_sds_port_configuration_agent *port_agent);
enum sci_status scic_sds_port_configuration_agent_initialize(
struct scic_sds_controller *controller,
struct scic_sds_port_configuration_agent *port_agent);
#endif /* _SCIC_SDS_PORT_CONFIGURATION_AGENT_H_ */

View File

@ -0,0 +1,223 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_PORT_REGISTERS_H_
#define _SCIC_SDS_PORT_REGISTERS_H_
/**
* This file contains a set of macros that assist in reading the SCU hardware
* registers.
*
*
*/
/**
* scu_transport_layer_read() -
*
* Macro to read the transport layer register associated with this port object.
*/
#define scu_transport_layer_read(port, reg) \
scu_register_read(\
scic_sds_port_get_controller(port), \
(port)->transport_layer_registers->reg \
)
/**
* scu_transport_layer_write() -
*
* Macro to write the transport layer register associated with this port object.
*/
#define scu_transport_layer_write(port, reg, value) \
scu_register_write(\
scic_sds_port_get_controller(port), \
(port)->transport_layer_registers->reg, \
(value) \
)
/**
* scu_port_task_scheduler_read() -
*
* Macro to read the port task scheduler register associated with this port
* object
*/
#define scu_port_task_scheduler_read(port, reg) \
scu_register_read(\
scic_sds_port_get_controller(port), \
(port)->port_task_scheduler_registers->reg \
)
/**
* scu_port_task_scheduler_write() -
*
* Macro to write the port task scheduler register associated with this port
* object
*/
#define scu_port_task_scheduler_write(port, reg, value) \
scu_register_write(\
scic_sds_port_get_controller(port), \
(port)->port_task_scheduler_registers->reg, \
(value) \
)
#define scu_port_viit_register_write(port, reg, value) \
scu_register_write(\
scic_sds_port_get_controller(port), \
(port)->viit_registers->reg, \
(value) \
)
/*
* ****************************************************************************
* * Transport Layer registers controlled by the port object
* **************************************************************************** */
/**
* SCU_TLCR_READ() -
*
* This macro reads the Transport layer control register
*/
#define SCU_TLCR_READ(port) \
scu_transport_layer_read(port, control)
/**
* SCU_TLCR_WRITE() -
*
* This macro writes the Transport layer control register
*/
#define SCU_TLCR_WRITE(port, value) \
scu_transport_layer_write(port, control, value)
/**
* SCU_TLADTR_READ() -
*
* This macro reads the Transport layer address translation register
*/
#define SCU_TLADTR_READ(port) \
scu_transport_layer_read(port, address_translation)
/**
* SCU_TLADTR_WRITE() -
*
* This macro writes the Transport layer address translation register
*/
#define SCU_TLADTR_WRITE(port) \
scu_transport_layer_write(port, address_translation, value)
/**
* SCU_STPTLDARNI_WRITE() -
*
* This macro writes the STP Transport Layer Direct Attached RNi register.
*/
#define SCU_STPTLDARNI_WRITE(port, index) \
scu_transport_layer_write(port, stp_rni, index)
/**
* SCU_STPTLDARNI_READ() -
*
* This macro reads the STP Transport Layer Direct Attached RNi register.
*/
#define SCU_STPTLDARNI_READ(port) \
scu_transport_layer_read(port, stp_rni)
/*
* ****************************************************************************
* * Port Task Scheduler registers controlled by the port object
* **************************************************************************** */
/**
* SCU_PTSxCR_READ() -
*
* Macro to read the port task scheduler control register
*/
#define SCU_PTSxCR_READ(port) \
scu_port_task_scheduler_read(port, control)
/**
* SCU_PTSxCR_WRITE() -
*
* Macro to write the port task scheduler control regsister
*/
#define SCU_PTSxCR_WRITE(port, value) \
scu_port_task_scheduler_write(port, control, value)
/*
* ****************************************************************************
* * Port PE Configuration registers
* **************************************************************************** */
/**
* SCU_PCSPExCR_WRITE() -
*
* Macro to write the PE Port Configuration Register
*/
#define SCU_PCSPExCR_WRITE(port, phy_id, value) \
scu_register_write(\
scic_sds_port_get_controller(port), \
(port)->port_pe_configuration_register[phy_id], \
(value) \
)
/**
* SCU_PCSPExCR_READ() -
*
* Macro to read the PE Port Configuration Regsiter
*/
#define SCU_PCSPExCR_READ(port, phy_id) \
scu_register_read(\
scic_sds_port_get_controller(port), \
(port)->port_pe_configuration_register[phy_id] \
)
#endif /* _SCIC_SDS_PORT_REGISTERS_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,602 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_REMOTE_DEVICE_H_
#define _SCIC_SDS_REMOTE_DEVICE_H_
/**
* This file contains the structures, constants, and prototypes for the
* struct scic_sds_remote_device object.
*
*
*/
#include "intel_sas.h"
#include "sci_base_remote_device.h"
#include "sci_base_request.h"
#include "scu_remote_node_context.h"
#include "scic_sds_remote_node_context.h"
struct scic_sds_controller;
struct scic_sds_port;
struct scic_sds_request;
struct scic_sds_remote_device_state_handler;
/**
* enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES -
*
* This is the enumeration of the ready substates for the
* struct scic_sds_remote_device.
*/
enum SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATES {
/**
* This is the initial state for the remote device ready substate.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_INITIAL,
/**
* This is the ready operational substate for the remote device. This is the
* normal operational state for a remote device.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_OPERATIONAL,
/**
* This is the suspended state for the remote device. This is the state that
* the device is placed in when a RNC suspend is received by the SCU hardware.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_SUSPENDED,
/**
* This is the final state that the device is placed in before a change to the
* base state machine.
*/
SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_FINAL,
SCIC_SDS_SSP_REMOTE_DEVICE_READY_MAX_SUBSTATES
};
/**
* enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES -
*
* This is the enumeration for the struct scic_sds_remote_device ready substates for
* the STP remote device.
*/
enum SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATES {
/**
* This is the idle substate for the stp remote device. When there are no
* active IO for the device it is is in this state.
*/
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
/**
* This is the command state for for the STP remote device. This state is
* entered when the device is processing a non-NCQ command. The device object
* will fail any new start IO requests until this command is complete.
*/
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
/**
* This is the NCQ state for the STP remote device. This state is entered
* when the device is processing an NCQ reuqest. It will remain in this state
* so long as there is one or more NCQ requests being processed.
*/
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ,
/**
* This is the NCQ error state for the STP remote device. This state is
* entered when an SDB error FIS is received by the device object while in the
* NCQ state. The device object will only accept a READ LOG command while in
* this state.
*/
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR,
#if !defined(DISABLE_ATAPI)
/**
* This is the ATAPI error state for the STP ATAPI remote device. This state is
* entered when ATAPI device sends error status FIS without data while the device
* object is in CMD state. A suspension event is expected in this state. The device
* object will resume right away.
*/
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR,
#endif
/**
* This is the READY substate indicates the device is waiting for the RESET task
* coming to be recovered from certain hardware specific error.
*/
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET,
SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES
};
/**
* enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES -
*
* This is the enumeration of the ready substates for the SMP REMOTE DEVICE.
*/
enum SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATES {
/**
* This is the ready operational substate for the remote device. This is the
* normal operational state for a remote device.
*/
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE,
/**
* This is the suspended state for the remote device. This is the state that
* the device is placed in when a RNC suspend is received by the SCU hardware.
*/
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES
};
/**
* struct scic_sds_remote_device - This structure contains the data for an SCU
* implementation of the SCU Core device data.
*
*
*/
struct scic_sds_remote_device {
/**
* This field is the common base for all remote device objects.
*/
struct sci_base_remote_device parent;
/**
* This field is the programmed device port width. This value is written to
* the RCN data structure to tell the SCU how many open connections this
* device can have.
*/
u32 device_port_width;
/**
* This field is the programmed connection rate for this remote device. It is
* used to program the TC with the maximum allowed connection rate.
*/
enum sci_sas_link_rate connection_rate;
/**
* This field contains the allowed target protocols for this remote device.
*/
struct smp_discover_response_protocols target_protocols;
/**
* This field contains the device SAS address.
*/
struct sci_sas_address device_address;
/**
* This filed is assinged the value of true if the device is directly attached
* to the port.
*/
bool is_direct_attached;
#if !defined(DISABLE_ATAPI)
/**
* This filed is assinged the value of true if the device is an ATAPI device.
*/
bool is_atapi;
#endif
/**
* This filed contains a pointer back to the port to which this device is
* assigned.
*/
struct scic_sds_port *owning_port;
/**
* This field contains the SCU silicon remote node context specific
* information.
*/
struct scic_sds_remote_node_context *rnc;
/**
* This field contains the stated request count for the remote device. The
* device can not reach the SCI_BASE_REMOTE_DEVICE_STATE_STOPPED until all
* requests are complete and the rnc_posted value is false.
*/
u32 started_request_count;
/**
* This field contains a pointer to the working request object. It is only
* used only for SATA requests since the unsolicited frames we get from the
* hardware have no Tag value to look up the io request object.
*/
struct scic_sds_request *working_request;
/**
* This field contains the reason for the remote device going not_ready. It is
* assigned in the state handlers and used in the state transition.
*/
u32 not_ready_reason;
/**
* This field is true if this remote device has an initialzied ready substate
* machine. SSP devices do not have a ready substate machine and STP devices
* have a ready substate machine.
*/
bool has_ready_substate_machine;
/**
* This field contains the state machine for the ready substate machine for
* this struct scic_sds_remote_device object.
*/
struct sci_base_state_machine ready_substate_machine;
/**
* This field maintains the set of state handlers for the remote device
* object. These are changed each time the remote device enters a new state.
*/
struct scic_sds_remote_device_state_handler *state_handlers;
};
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_HANDLER_T)(
struct scic_sds_remote_device *this_device);
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T)(
struct scic_sds_remote_device *this_device,
u32 suspend_type);
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T)(
struct scic_sds_remote_device *this_device);
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T)(
struct scic_sds_remote_device *this_device,
u32 frame_index);
typedef enum sci_status (*SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T)(
struct scic_sds_remote_device *this_device,
u32 event_code);
typedef void (*SCIC_SDS_REMOTE_DEVICE_READY_NOT_READY_HANDLER_T)(
struct scic_sds_remote_device *this_device);
/**
* struct scic_sds_remote_device_state_handler - This structure conains the
* state handlers that are needed to process requests for the SCU remote
* device objects.
*
*
*/
struct scic_sds_remote_device_state_handler {
struct sci_base_remote_device_state_handler parent;
SCIC_SDS_REMOTE_DEVICE_SUSPEND_HANDLER_T suspend_handler;
SCIC_SDS_REMOTE_DEVICE_RESUME_HANDLER_T resume_handler;
SCIC_SDS_REMOTE_DEVICE_EVENT_HANDLER_T event_handler;
SCIC_SDS_REMOTE_DEVICE_FRAME_HANDLER_T frame_handler;
};
extern const struct sci_base_state scic_sds_remote_device_state_table[];
extern const struct sci_base_state scic_sds_ssp_remote_device_ready_substate_table[];
extern const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[];
extern const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[];
extern struct scic_sds_remote_device_state_handler
scic_sds_remote_device_state_handler_table[];
extern struct scic_sds_remote_device_state_handler
scic_sds_ssp_remote_device_ready_substate_handler_table[];
extern struct scic_sds_remote_device_state_handler
scic_sds_stp_remote_device_ready_substate_handler_table[];
extern struct scic_sds_remote_device_state_handler
scic_sds_smp_remote_device_ready_substate_handler_table[];
/**
* scic_sds_remote_device_increment_request_count() -
*
* This macro incrments the request count for this device
*/
#define scic_sds_remote_device_increment_request_count(this_device) \
((this_device)->started_request_count++)
/**
* scic_sds_remote_device_decrement_request_count() -
*
* This macro decrements the request count for this device. This count will
* never decrment past 0.
*/
#define scic_sds_remote_device_decrement_request_count(this_device) \
((this_device)->started_request_count > 0 ? \
(this_device)->started_request_count-- : 0)
/**
* scic_sds_remote_device_get_request_count() -
*
* This is a helper macro to return the current device request count.
*/
#define scic_sds_remote_device_get_request_count(this_device) \
((this_device)->started_request_count)
/**
* scic_sds_remote_device_get_port() -
*
* This macro returns the owning port of this remote device obejct.
*/
#define scic_sds_remote_device_get_port(this_device) \
((this_device)->owning_port)
/**
* scic_sds_remote_device_get_controller() -
*
* This macro returns the controller object that contains this device object
*/
#define scic_sds_remote_device_get_controller(this_device) \
scic_sds_port_get_controller(scic_sds_remote_device_get_port(this_device))
/**
* scic_sds_remote_device_set_state_handlers() -
*
* This macro sets the remote device state handlers pointer and is set on entry
* to each device state.
*/
#define scic_sds_remote_device_set_state_handlers(this_device, handlers) \
((this_device)->state_handlers = (handlers))
/**
* scic_sds_remote_device_get_base_state_machine() -
*
* This macro returns the base sate machine object for the remote device.
*/
#define scic_sds_remote_device_get_base_state_machine(this_device) \
(&(this_device)->parent.state_machine)
/**
* scic_sds_remote_device_get_ready_substate_machine() -
*
* This macro returns the remote device ready substate machine
*/
#define scic_sds_remote_device_get_ready_substate_machine(this_device) \
(&(this_device)->ready_substate_machine)
/**
* scic_sds_remote_device_get_port() -
*
* This macro returns the owning port of this device
*/
#define scic_sds_remote_device_get_port(this_device) \
((this_device)->owning_port)
/**
* scic_sds_remote_device_get_sequence() -
*
* This macro returns the remote device sequence value
*/
#define scic_sds_remote_device_get_sequence(this_device) \
(\
scic_sds_remote_device_get_controller(this_device)-> \
remote_device_sequence[(this_device)->rnc->remote_node_index] \
)
/**
* scic_sds_remote_device_get_controller_peg() -
*
* This macro returns the controllers protocol engine group
*/
#define scic_sds_remote_device_get_controller_peg(this_device) \
(\
scic_sds_controller_get_protocol_engine_group(\
scic_sds_port_get_controller(\
scic_sds_remote_device_get_port(this_device) \
) \
) \
)
/**
* scic_sds_remote_device_get_port_index() -
*
* This macro returns the port index for the devices owning port
*/
#define scic_sds_remote_device_get_port_index(this_device) \
(scic_sds_port_get_index(scic_sds_remote_device_get_port(this_device)))
/**
* scic_sds_remote_device_get_index() -
*
* This macro returns the remote node index for this device object
*/
#define scic_sds_remote_device_get_index(this_device) \
((this_device)->rnc->remote_node_index)
/**
* scic_sds_remote_device_build_command_context() -
*
* This macro builds a remote device context for the SCU post request operation
*/
#define scic_sds_remote_device_build_command_context(device, command) \
((command) \
| (scic_sds_remote_device_get_controller_peg((device)) << SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT) \
| (scic_sds_remote_device_get_port_index((device)) << SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT) \
| (scic_sds_remote_device_get_index((device))) \
)
/**
* scic_sds_remote_device_set_working_request() -
*
* This macro makes the working request assingment for the remote device
* object. To clear the working request use this macro with a NULL request
* object.
*/
#define scic_sds_remote_device_set_working_request(device, request) \
((device)->working_request = (request))
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_remote_device_frame_handler(
struct scic_sds_remote_device *this_device,
u32 frame_index);
enum sci_status scic_sds_remote_device_event_handler(
struct scic_sds_remote_device *this_device,
u32 event_code);
enum sci_status scic_sds_remote_device_start_io(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *this_device,
struct scic_sds_request *io_request);
enum sci_status scic_sds_remote_device_complete_io(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *this_device,
struct scic_sds_request *io_request);
enum sci_status scic_sds_remote_device_resume(
struct scic_sds_remote_device *this_device);
enum sci_status scic_sds_remote_device_suspend(
struct scic_sds_remote_device *this_device,
u32 suspend_type);
enum sci_status scic_sds_remote_device_start_task(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *this_device,
struct scic_sds_request *io_request);
void scic_sds_remote_device_post_request(
struct scic_sds_remote_device *this_device,
u32 request);
#if !defined(DISABLE_ATAPI)
bool scic_sds_remote_device_is_atapi(
struct scic_sds_remote_device *this_device);
#else /* !defined(DISABLE_ATAPI) */
#define scic_sds_remote_device_is_atapi(this_device) false
#endif /* !defined(DISABLE_ATAPI) */
/* --------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------- */
void scic_sds_remote_device_start_request(
struct scic_sds_remote_device *this_device,
struct scic_sds_request *the_request,
enum sci_status status);
void scic_sds_remote_device_continue_request(
struct scic_sds_remote_device *this_device);
enum sci_status scic_sds_remote_device_default_start_handler(
struct sci_base_remote_device *this_device);
enum sci_status scic_sds_remote_device_default_fail_handler(
struct sci_base_remote_device *this_device);
enum sci_status scic_sds_remote_device_default_destruct_handler(
struct sci_base_remote_device *this_device);
enum sci_status scic_sds_remote_device_default_reset_handler(
struct sci_base_remote_device *device);
enum sci_status scic_sds_remote_device_default_reset_complete_handler(
struct sci_base_remote_device *device);
enum sci_status scic_sds_remote_device_default_start_request_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request);
enum sci_status scic_sds_remote_device_default_complete_request_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request);
enum sci_status scic_sds_remote_device_default_continue_request_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request);
enum sci_status scic_sds_remote_device_default_suspend_handler(
struct scic_sds_remote_device *this_device,
u32 suspend_type);
enum sci_status scic_sds_remote_device_default_resume_handler(
struct scic_sds_remote_device *this_device);
enum sci_status scic_sds_remote_device_default_frame_handler(
struct scic_sds_remote_device *this_device,
u32 frame_index);
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_remote_device_ready_state_stop_handler(
struct sci_base_remote_device *device);
enum sci_status scic_sds_remote_device_ready_state_reset_handler(
struct sci_base_remote_device *device);
enum sci_status scic_sds_remote_device_general_frame_handler(
struct scic_sds_remote_device *this_device,
u32 frame_index);
enum sci_status scic_sds_remote_device_general_event_handler(
struct scic_sds_remote_device *this_device,
u32 event_code);
enum sci_status scic_sds_ssp_remote_device_ready_suspended_substate_resume_handler(
struct scic_sds_remote_device *this_device);
/* --------------------------------------------------------------------------- */
#endif /* _SCIC_SDS_REMOTE_DEVICE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,342 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
#define _SCIC_SDS_REMOTE_NODE_CONTEXT_H_
/**
* This file contains the structures, constants, and prototypes associated with
* the remote node context in the silicon. It exists to model and manage
* the remote node context in the silicon.
*
*
*/
#include "sci_types.h"
#include "sci_base_state.h"
#include "sci_base_state_machine.h"
/* --------------------------------------------------------------------------- */
/**
*
*
* This constant represents an invalid remote device id, it is used to program
* the STPDARNI register so the driver knows when it has received a SIGNATURE
* FIS from the SCU.
*/
#define SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX 0x0FFF
#define SCU_HARDWARE_SUSPENSION (0)
#define SCI_SOFTWARE_SUSPENSION (1)
struct scic_sds_request;
struct scic_sds_remote_device;
struct scic_sds_remote_node_context;
typedef void (*SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)(void *);
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION)(
struct scic_sds_remote_node_context *this_rnc,
SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
void *callback_parameter
);
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION)(
struct scic_sds_remote_node_context *this_rnc,
u32 suspension_type,
SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK the_callback,
void *callback_parameter
);
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST)(
struct scic_sds_remote_node_context *this_rnc,
struct scic_sds_request *the_request
);
typedef enum sci_status (*SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER)(
struct scic_sds_remote_node_context *this_rnc,
u32 event_code
);
/* --------------------------------------------------------------------------- */
struct scic_sds_remote_node_context_handlers {
/**
* This handle is invoked to stop the RNC. The callback is invoked when after
* the hardware notification that the RNC has been invalidated.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION destruct_handler;
/**
* This handler is invoked when there is a request to suspend the RNC. The
* callback is invoked after the hardware notification that the remote node is
* suspended.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_SUSPEND_OPERATION suspend_handler;
/**
* This handler is invoked when there is a request to resume the RNC. The
* callback is invoked when after the RNC has reached the ready state.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_OPERATION resume_handler;
/**
* This handler is invoked when there is a request to start an io request
* operation.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_io_handler;
/**
* This handler is invoked when there is a request to start a task request
* operation.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_IO_REQUEST start_task_handler;
/**
* This handler is invoked where there is an RNC event that must be processed.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_EVENT_HANDLER event_handler;
};
/* --------------------------------------------------------------------------- */
/**
*
*
* This is the enumeration of the remote node context states.
*/
enum scis_sds_remote_node_context_states {
/**
* This state is the initial state for a remote node context. On a resume
* request the remote node context will transition to the posting state.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_INITIAL_STATE,
/**
* This is a transition state that posts the RNi to the hardware. Once the RNC
* is posted the remote node context will be made ready.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_POSTING_STATE,
/**
* This is a transition state that will post an RNC invalidate to the
* hardware. Once the invalidate is complete the remote node context will
* transition to the posting state.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_INVALIDATING_STATE,
/**
* This is a transition state that will post an RNC resume to the hardare.
* Once the event notification of resume complete is received the remote node
* context will transition to the ready state.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_RESUMING_STATE,
/**
* This is the state that the remote node context must be in to accept io
* request operations.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_READY_STATE,
/**
* This is the state that the remote node context transitions to when it gets
* a TX suspend notification from the hardware.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_TX_SUSPENDED_STATE,
/**
* This is the state that the remote node context transitions to when it gets
* a TX RX suspend notification from the hardware.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_TX_RX_SUSPENDED_STATE,
/**
* This state is a wait state for the remote node context that waits for a
* suspend notification from the hardware. This state is entered when either
* there is a request to supend the remote node context or when there is a TC
* completion where the remote node will be suspended by the hardware.
*/
SCIC_SDS_REMOTE_NODE_CONTEXT_AWAIT_SUSPENSION_STATE,
SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES
};
/**
*
*
* This enumeration is used to define the end destination state for the remote
* node context.
*/
enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE {
SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_UNSPECIFIED,
SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_READY,
SCIC_SDS_REMOTE_NODE_DESTINATION_STATE_FINAL
};
/**
* struct scic_sds_remote_node_context - This structure contains the data
* associated with the remote node context object. The remote node context
* (RNC) object models the the remote device information necessary to manage
* the silicon RNC.
*
*
*/
struct scic_sds_remote_node_context {
/*
* parent object
*/
struct sci_base_object parent;
/**
* This pointer simply points to the remote device object containing
* this RNC.
*
* @todo Consider making the device pointer the associated object of the
* the parent object.
*/
struct scic_sds_remote_device *device;
/**
* This field indicates the remote node index (RNI) associated with
* this RNC.
*/
u16 remote_node_index;
/**
* This field is the recored suspension code or the reason for the remote node
* context suspension.
*/
u32 suspension_code;
/**
* This field is true if the remote node context is resuming from its current
* state. This can cause an automatic resume on receiving a suspension
* notification.
*/
enum SCIC_SDS_REMOTE_NODE_CONTEXT_DESTINATION_STATE destination_state;
/**
* This field contains the callback function that the user requested to be
* called when the requested state transition is complete.
*/
SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK user_callback;
/**
* This field contains the parameter that is called when the user requested
* state transition is completed.
*/
void *user_cookie;
/**
* This field contains the data for the object's state machine.
*/
struct sci_base_state_machine state_machine;
struct scic_sds_remote_node_context_handlers *state_handlers;
};
/* --------------------------------------------------------------------------- */
extern const struct sci_base_state scic_sds_remote_node_context_state_table[];
extern struct scic_sds_remote_node_context_handlers
scic_sds_remote_node_context_state_handler_table[
SCIC_SDS_REMOTE_NODE_CONTEXT_MAX_STATES];
/* --------------------------------------------------------------------------- */
void scic_sds_remote_node_context_construct(
struct scic_sds_remote_device *device,
struct scic_sds_remote_node_context *rnc,
u16 remote_node_index);
void scic_sds_remote_node_context_construct_buffer(
struct scic_sds_remote_node_context *rnc);
bool scic_sds_remote_node_context_is_ready(
struct scic_sds_remote_node_context *this_rnc);
#define scic_sds_remote_node_context_set_remote_node_index(rnc, rni) \
((rnc)->remote_node_index = (rni))
#define scic_sds_remote_node_context_get_remote_node_index(rcn) \
((rnc)->remote_node_index)
#define scic_sds_remote_node_context_event_handler(rnc, event_code) \
((rnc)->state_handlers->event_handler(rnc, event_code))
#define scic_sds_remote_node_context_resume(rnc, callback, parameter) \
((rnc)->state_handlers->resume_handler(rnc, callback, parameter))
#define scic_sds_remote_node_context_suspend(rnc, suspend_type, callback, parameter) \
((rnc)->state_handlers->suspend_handler(rnc, suspend_type, callback, parameter))
#define scic_sds_remote_node_context_destruct(rnc, callback, parameter) \
((rnc)->state_handlers->destruct_handler(rnc, callback, parameter))
#define scic_sds_remote_node_context_start_io(rnc, request) \
((rnc)->state_handlers->start_io_handler(rnc, request))
#define scic_sds_remote_node_context_start_task(rnc, task) \
((rnc)->state_handlers->start_task_handler(rnc, task))
/* --------------------------------------------------------------------------- */
#endif /* _SCIC_SDS_REMOTE_NODE_CONTEXT_H_ */

View File

@ -0,0 +1,600 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the implementation of the SCIC_SDS_REMOTE_NODE_TABLE
* public, protected, and private methods.
*
*
*/
#include "sci_util.h"
#include "sci_environment.h"
#include "scic_sds_remote_node_table.h"
#include "scic_sds_remote_node_context.h"
/**
*
* @remote_node_table: This is the remote node index table from which the
* selection will be made.
* @group_table_index: This is the index to the group table from which to
* search for an available selection.
*
* This routine will find the bit position in absolute bit terms of the next 32
* + bit position. If there are available bits in the first u32 then it is
* just bit position. u32 This is the absolute bit position for an available
* group.
*/
static u32 scic_sds_remote_node_table_get_group_index(
struct scic_remote_node_table *remote_node_table,
u32 group_table_index)
{
u32 dword_index;
u32 *group_table;
u32 bit_index;
group_table = remote_node_table->remote_node_groups[group_table_index];
for (dword_index = 0; dword_index < remote_node_table->group_array_size; dword_index++) {
if (group_table[dword_index] != 0) {
for (bit_index = 0; bit_index < 32; bit_index++) {
if ((group_table[dword_index] & (1 << bit_index)) != 0) {
return (dword_index * 32) + bit_index;
}
}
}
}
return SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX;
}
/**
*
* @out]: remote_node_table This the remote node table in which to clear the
* selector.
* @set_index: This is the remote node selector in which the change will be
* made.
* @group_index: This is the bit index in the table to be modified.
*
* This method will clear the group index entry in the specified group index
* table. none
*/
static void scic_sds_remote_node_table_clear_group_index(
struct scic_remote_node_table *remote_node_table,
u32 group_table_index,
u32 group_index)
{
u32 dword_index;
u32 bit_index;
u32 *group_table;
BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
dword_index = group_index / 32;
bit_index = group_index % 32;
group_table = remote_node_table->remote_node_groups[group_table_index];
group_table[dword_index] = group_table[dword_index] & ~(1 << bit_index);
}
/**
*
* @out]: remote_node_table This the remote node table in which to set the
* selector.
* @group_table_index: This is the remote node selector in which the change
* will be made.
* @group_index: This is the bit position in the table to be modified.
*
* This method will set the group index bit entry in the specified gropu index
* table. none
*/
static void scic_sds_remote_node_table_set_group_index(
struct scic_remote_node_table *remote_node_table,
u32 group_table_index,
u32 group_index)
{
u32 dword_index;
u32 bit_index;
u32 *group_table;
BUG_ON(group_table_index >= SCU_STP_REMOTE_NODE_COUNT);
BUG_ON(group_index >= (u32)(remote_node_table->group_array_size * 32));
dword_index = group_index / 32;
bit_index = group_index % 32;
group_table = remote_node_table->remote_node_groups[group_table_index];
group_table[dword_index] = group_table[dword_index] | (1 << bit_index);
}
/**
*
* @out]: remote_node_table This is the remote node table in which to modify
* the remote node availability.
* @remote_node_index: This is the remote node index that is being returned to
* the table.
*
* This method will set the remote to available in the remote node allocation
* table. none
*/
static void scic_sds_remote_node_table_set_node_index(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_index)
{
u32 dword_location;
u32 dword_remainder;
u32 slot_normalized;
u32 slot_position;
BUG_ON(
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
<= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
);
dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
remote_node_table->available_remote_nodes[dword_location] |=
1 << (slot_normalized + slot_position);
}
/**
*
* @out]: remote_node_table This is the remote node table from which to clear
* the available remote node bit.
* @remote_node_index: This is the remote node index which is to be cleared
* from the table.
*
* This method clears the remote node index from the table of available remote
* nodes. none
*/
static void scic_sds_remote_node_table_clear_node_index(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_index)
{
u32 dword_location;
u32 dword_remainder;
u32 slot_position;
u32 slot_normalized;
BUG_ON(
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
<= (remote_node_index / SCU_STP_REMOTE_NODE_COUNT)
);
dword_location = remote_node_index / SCIC_SDS_REMOTE_NODES_PER_DWORD;
dword_remainder = remote_node_index % SCIC_SDS_REMOTE_NODES_PER_DWORD;
slot_normalized = (dword_remainder / SCU_STP_REMOTE_NODE_COUNT) * sizeof(u32);
slot_position = remote_node_index % SCU_STP_REMOTE_NODE_COUNT;
remote_node_table->available_remote_nodes[dword_location] &=
~(1 << (slot_normalized + slot_position));
}
/**
*
* @out]: remote_node_table The remote node table from which the slot will be
* cleared.
* @group_index: The index for the slot that is to be cleared.
*
* This method clears the entire table slot at the specified slot index. none
*/
static void scic_sds_remote_node_table_clear_group(
struct scic_remote_node_table *remote_node_table,
u32 group_index)
{
u32 dword_location;
u32 dword_remainder;
u32 dword_value;
BUG_ON(
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
<= (group_index / SCU_STP_REMOTE_NODE_COUNT)
);
dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
dword_value = remote_node_table->available_remote_nodes[dword_location];
dword_value &= ~(SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
remote_node_table->available_remote_nodes[dword_location] = dword_value;
}
/**
*
* @remote_node_table:
*
* THis method sets an entire remote node group in the remote node table.
*/
static void scic_sds_remote_node_table_set_group(
struct scic_remote_node_table *remote_node_table,
u32 group_index)
{
u32 dword_location;
u32 dword_remainder;
u32 dword_value;
BUG_ON(
(remote_node_table->available_nodes_array_size * SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD)
<= (group_index / SCU_STP_REMOTE_NODE_COUNT)
);
dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
dword_value = remote_node_table->available_remote_nodes[dword_location];
dword_value |= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
remote_node_table->available_remote_nodes[dword_location] = dword_value;
}
/**
*
* @remote_node_table: This is the remote node table that for which the group
* value is to be returned.
* @group_index: This is the group index to use to find the group value.
*
* This method will return the group value for the specified group index. The
* bit values at the specified remote node group index.
*/
static u8 scic_sds_remote_node_table_get_group_value(
struct scic_remote_node_table *remote_node_table,
u32 group_index)
{
u32 dword_location;
u32 dword_remainder;
u32 dword_value;
dword_location = group_index / SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
dword_remainder = group_index % SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD;
dword_value = remote_node_table->available_remote_nodes[dword_location];
dword_value &= (SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE << (dword_remainder * 4));
dword_value = dword_value >> (dword_remainder * 4);
return (u8)dword_value;
}
/**
*
* @out]: remote_node_table The remote that which is to be initialized.
* @remote_node_entries: The number of entries to put in the table.
*
* This method will initialize the remote node table for use. none
*/
void scic_sds_remote_node_table_initialize(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_entries)
{
u32 index;
/*
* Initialize the raw data we could improve the speed by only initializing
* those entries that we are actually going to be used */
memset(
remote_node_table->available_remote_nodes,
0x00,
sizeof(remote_node_table->available_remote_nodes)
);
memset(
remote_node_table->remote_node_groups,
0x00,
sizeof(remote_node_table->remote_node_groups)
);
/* Initialize the available remote node sets */
remote_node_table->available_nodes_array_size = (u16)
(remote_node_entries / SCIC_SDS_REMOTE_NODES_PER_DWORD)
+ ((remote_node_entries % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0);
/* Initialize each full DWORD to a FULL SET of remote nodes */
for (index = 0; index < remote_node_entries; index++) {
scic_sds_remote_node_table_set_node_index(remote_node_table, index);
}
remote_node_table->group_array_size = (u16)
(remote_node_entries / (SCU_STP_REMOTE_NODE_COUNT * 32))
+ ((remote_node_entries % (SCU_STP_REMOTE_NODE_COUNT * 32)) != 0);
for (index = 0; index < (remote_node_entries / SCU_STP_REMOTE_NODE_COUNT); index++) {
/*
* These are all guaranteed to be full slot values so fill them in the
* available sets of 3 remote nodes */
scic_sds_remote_node_table_set_group_index(remote_node_table, 2, index);
}
/* Now fill in any remainders that we may find */
if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 2) {
scic_sds_remote_node_table_set_group_index(remote_node_table, 1, index);
} else if ((remote_node_entries % SCU_STP_REMOTE_NODE_COUNT) == 1) {
scic_sds_remote_node_table_set_group_index(remote_node_table, 0, index);
}
}
/**
*
* @out]: remote_node_table The remote node table from which to allocate a
* remote node.
* @table_index: The group index that is to be used for the search.
*
* This method will allocate a single RNi from the remote node table. The
* table index will determine from which remote node group table to search.
* This search may fail and another group node table can be specified. The
* function is designed to allow a serach of the available single remote node
* group up to the triple remote node group. If an entry is found in the
* specified table the remote node is removed and the remote node groups are
* updated. The RNi value or an invalid remote node context if an RNi can not
* be found.
*/
static u16 scic_sds_remote_node_table_allocate_single_remote_node(
struct scic_remote_node_table *remote_node_table,
u32 group_table_index)
{
u8 index;
u8 group_value;
u32 group_index;
u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
group_index = scic_sds_remote_node_table_get_group_index(
remote_node_table, group_table_index);
/* We could not find an available slot in the table selector 0 */
if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
group_value = scic_sds_remote_node_table_get_group_value(
remote_node_table, group_index);
for (index = 0; index < SCU_STP_REMOTE_NODE_COUNT; index++) {
if (((1 << index) & group_value) != 0) {
/* We have selected a bit now clear it */
remote_node_index = (u16)(group_index * SCU_STP_REMOTE_NODE_COUNT
+ index);
scic_sds_remote_node_table_clear_group_index(
remote_node_table, group_table_index, group_index
);
scic_sds_remote_node_table_clear_node_index(
remote_node_table, remote_node_index
);
if (group_table_index > 0) {
scic_sds_remote_node_table_set_group_index(
remote_node_table, group_table_index - 1, group_index
);
}
break;
}
}
}
return remote_node_index;
}
/**
*
* @remote_node_table: This is the remote node table from which to allocate the
* remote node entries.
* @group_table_index: THis is the group table index which must equal two (2)
* for this operation.
*
* This method will allocate three consecutive remote node context entries. If
* there are no remaining triple entries the function will return a failure.
* The remote node index that represents three consecutive remote node entries
* or an invalid remote node context if none can be found.
*/
static u16 scic_sds_remote_node_table_allocate_triple_remote_node(
struct scic_remote_node_table *remote_node_table,
u32 group_table_index)
{
u32 group_index;
u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
group_index = scic_sds_remote_node_table_get_group_index(
remote_node_table, group_table_index);
if (group_index != SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX) {
remote_node_index = (u16)group_index * SCU_STP_REMOTE_NODE_COUNT;
scic_sds_remote_node_table_clear_group_index(
remote_node_table, group_table_index, group_index
);
scic_sds_remote_node_table_clear_group(
remote_node_table, group_index
);
}
return remote_node_index;
}
/**
*
* @remote_node_table: This is the remote node table from which the remote node
* allocation is to take place.
* @remote_node_count: This is ther remote node count which is one of
* SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3).
*
* This method will allocate a remote node that mataches the remote node count
* specified by the caller. Valid values for remote node count is
* SCU_SSP_REMOTE_NODE_COUNT(1) or SCU_STP_REMOTE_NODE_COUNT(3). u16 This is
* the remote node index that is returned or an invalid remote node context.
*/
u16 scic_sds_remote_node_table_allocate_remote_node(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_count)
{
u16 remote_node_index = SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX;
if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
remote_node_index =
scic_sds_remote_node_table_allocate_single_remote_node(
remote_node_table, 0);
if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
remote_node_index =
scic_sds_remote_node_table_allocate_single_remote_node(
remote_node_table, 1);
}
if (remote_node_index == SCIC_SDS_REMOTE_NODE_CONTEXT_INVALID_INDEX) {
remote_node_index =
scic_sds_remote_node_table_allocate_single_remote_node(
remote_node_table, 2);
}
} else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
remote_node_index =
scic_sds_remote_node_table_allocate_triple_remote_node(
remote_node_table, 2);
}
return remote_node_index;
}
/**
*
* @remote_node_table:
*
* This method will free a single remote node index back to the remote node
* table. This routine will update the remote node groups
*/
static void scic_sds_remote_node_table_release_single_remote_node(
struct scic_remote_node_table *remote_node_table,
u16 remote_node_index)
{
u32 group_index;
u8 group_value;
group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
group_value = scic_sds_remote_node_table_get_group_value(remote_node_table, group_index);
/*
* Assert that we are not trying to add an entry to a slot that is already
* full. */
BUG_ON(group_value == SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE);
if (group_value == 0x00) {
/*
* There are no entries in this slot so it must be added to the single
* slot table. */
scic_sds_remote_node_table_set_group_index(remote_node_table, 0, group_index);
} else if ((group_value & (group_value - 1)) == 0) {
/*
* There is only one entry in this slot so it must be moved from the
* single slot table to the dual slot table */
scic_sds_remote_node_table_clear_group_index(remote_node_table, 0, group_index);
scic_sds_remote_node_table_set_group_index(remote_node_table, 1, group_index);
} else {
/*
* There are two entries in the slot so it must be moved from the dual
* slot table to the tripple slot table. */
scic_sds_remote_node_table_clear_group_index(remote_node_table, 1, group_index);
scic_sds_remote_node_table_set_group_index(remote_node_table, 2, group_index);
}
scic_sds_remote_node_table_set_node_index(remote_node_table, remote_node_index);
}
/**
*
* @remote_node_table: This is the remote node table to which the remote node
* index is to be freed.
*
* This method will release a group of three consecutive remote nodes back to
* the free remote nodes.
*/
static void scic_sds_remote_node_table_release_triple_remote_node(
struct scic_remote_node_table *remote_node_table,
u16 remote_node_index)
{
u32 group_index;
group_index = remote_node_index / SCU_STP_REMOTE_NODE_COUNT;
scic_sds_remote_node_table_set_group_index(
remote_node_table, 2, group_index
);
scic_sds_remote_node_table_set_group(remote_node_table, group_index);
}
/**
*
* @remote_node_table: The remote node table to which the remote node index is
* to be freed.
* @remote_node_count: This is the count of consecutive remote nodes that are
* to be freed.
*
* This method will release the remote node index back into the remote node
* table free pool.
*/
void scic_sds_remote_node_table_release_remote_node_index(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_count,
u16 remote_node_index)
{
if (remote_node_count == SCU_SSP_REMOTE_NODE_COUNT) {
scic_sds_remote_node_table_release_single_remote_node(
remote_node_table, remote_node_index);
} else if (remote_node_count == SCU_STP_REMOTE_NODE_COUNT) {
scic_sds_remote_node_table_release_triple_remote_node(
remote_node_table, remote_node_index);
}
}

View File

@ -0,0 +1,196 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_REMOTE_NODE_TABLE_H_
#define _SCIC_SDS_REMOTE_NODE_TABLE_H_
/**
* This file contains the structures, constants and prototypes used for the
* remote node table.
*
*
*/
#include "sci_types.h"
#include "sci_controller_constants.h"
/**
*
*
* Remote node sets are sets of remote node index in the remtoe node table The
* SCU hardware requires that STP remote node entries take three consecutive
* remote node index so the table is arranged in sets of three. The bits are
* used as 0111 0111 to make a byte and the bits define the set of three remote
* nodes to use as a sequence.
*/
#define SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE 2
/**
*
*
* Since the remote node table is organized as DWORDS take the remote node sets
* in bytes and represent them in DWORDs. The lowest ordered bits are the ones
* used in case full DWORD is not being used. i.e. 0000 0000 0000 0000 0111
* 0111 0111 0111 // if only a single WORD is in use in the DWORD.
*/
#define SCIC_SDS_REMOTE_NODE_SETS_PER_DWORD \
(sizeof(u32) * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
/**
*
*
* This is a count of the numeber of remote nodes that can be represented in a
* byte
*/
#define SCIC_SDS_REMOTE_NODES_PER_BYTE \
(SCU_STP_REMOTE_NODE_COUNT * SCIC_SDS_REMOTE_NODE_SETS_PER_BYTE)
/**
*
*
* This is a count of the number of remote nodes that can be represented in a
* DWROD
*/
#define SCIC_SDS_REMOTE_NODES_PER_DWORD \
(sizeof(u32) * SCIC_SDS_REMOTE_NODES_PER_BYTE)
/**
*
*
* This is the number of bits in a remote node group
*/
#define SCIC_SDS_REMOTE_NODES_BITS_PER_GROUP 4
#define SCIC_SDS_REMOTE_NODE_TABLE_INVALID_INDEX (0xFFFFFFFF)
#define SCIC_SDS_REMOTE_NODE_TABLE_FULL_SLOT_VALUE (0x07)
#define SCIC_SDS_REMOTE_NODE_TABLE_EMPTY_SLOT_VALUE (0x00)
/**
*
*
* Expander attached sata remote node count
*/
#define SCU_STP_REMOTE_NODE_COUNT 3
/**
*
*
* Expander or direct attached ssp remote node count
*/
#define SCU_SSP_REMOTE_NODE_COUNT 1
/**
*
*
* Direct attached STP remote node count
*/
#define SCU_SATA_REMOTE_NODE_COUNT 1
/**
* struct scic_remote_node_table -
*
*
*/
struct scic_remote_node_table {
/**
* This field contains the array size in dwords
*/
u16 available_nodes_array_size;
/**
* This field contains the array size of the
*/
u16 group_array_size;
/**
* This field is the array of available remote node entries in bits.
* Because of the way STP remote node data is allocated on the SCU hardware
* the remote nodes must occupy three consecutive remote node context
* entries. For ease of allocation and de-allocation we have broken the
* sets of three into a single nibble. When the STP RNi is allocated all
* of the bits in the nibble are cleared. This math results in a table size
* of MAX_REMOTE_NODES / CONSECUTIVE RNi ENTRIES for STP / 2 entries per byte.
*/
u32 available_remote_nodes[
(SCI_MAX_REMOTE_DEVICES / SCIC_SDS_REMOTE_NODES_PER_DWORD)
+ ((SCI_MAX_REMOTE_DEVICES % SCIC_SDS_REMOTE_NODES_PER_DWORD) != 0)];
/**
* This field is the nibble selector for the above table. There are three
* possible selectors each for fast lookup when trying to find one, two or
* three remote node entries.
*/
u32 remote_node_groups[
SCU_STP_REMOTE_NODE_COUNT][
(SCI_MAX_REMOTE_DEVICES / (32 * SCU_STP_REMOTE_NODE_COUNT))
+ ((SCI_MAX_REMOTE_DEVICES % (32 * SCU_STP_REMOTE_NODE_COUNT)) != 0)];
};
/* --------------------------------------------------------------------------- */
void scic_sds_remote_node_table_initialize(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_entries);
u16 scic_sds_remote_node_table_allocate_remote_node(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_count);
void scic_sds_remote_node_table_release_remote_node_index(
struct scic_remote_node_table *remote_node_table,
u32 remote_node_count,
u16 remote_node_index);
#endif /* _SCIC_SDS_REMOTE_NODE_TABLE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,484 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_IO_REQUEST_H_
#define _SCIC_SDS_IO_REQUEST_H_
/**
* This file contains the structures, constants and prototypes for the
* SCIC_SDS_IO_REQUEST object.
*
*
*/
#include "scic_io_request.h"
#include "sci_base_request.h"
#include "scu_task_context.h"
#include "intel_sas.h"
struct scic_sds_controller;
struct scic_sds_remote_device;
struct scic_sds_io_request_state_handler;
/**
* enum _SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATES - This enumeration
* depicts all of the substates for a task management request to be
* performed in the STARTED super-state.
*
*
*/
enum scic_sds_raw_request_started_task_mgmt_substates {
/**
* The AWAIT_TC_COMPLETION sub-state indicates that the started raw
* task management request is waiting for the transmission of the
* initial frame (i.e. command, task, etc.).
*/
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION,
/**
* This sub-state indicates that the started task management request
* is waiting for the reception of an unsolicited frame
* (i.e. response IU).
*/
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE,
};
/**
* enum _SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATES - This enumeration depicts all
* of the substates for a SMP request to be performed in the STARTED
* super-state.
*
*
*/
enum scic_sds_smp_request_started_substates {
/**
* This sub-state indicates that the started task management request
* is waiting for the reception of an unsolicited frame
* (i.e. response IU).
*/
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE,
/**
* The AWAIT_TC_COMPLETION sub-state indicates that the started SMP request is
* waiting for the transmission of the initial frame (i.e. command, task, etc.).
*/
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION,
};
/**
* struct SCIC_SDS_IO_REQUEST - This structure contains or references all of
* the data necessary to process a task management or normal IO request.
*
*
*/
struct scic_sds_request {
/**
* This field indictes the parent object of the request.
*/
struct sci_base_request parent;
void *user_request;
/**
* This field simply points to the controller to which this IO request
* is associated.
*/
struct scic_sds_controller *owning_controller;
/**
* This field simply points to the remote device to which this IO request
* is associated.
*/
struct scic_sds_remote_device *target_device;
/**
* This field is utilized to determine if the SCI user is managing
* the IO tag for this request or if the core is managing it.
*/
bool was_tag_assigned_by_user;
/**
* This field indicates the IO tag for this request. The IO tag is
* comprised of the task_index and a sequence count. The sequence count
* is utilized to help identify tasks from one life to another.
*/
u16 io_tag;
/**
* This field specifies the protocol being utilized for this
* IO request.
*/
SCIC_TRANSPORT_PROTOCOL protocol;
/**
* This field indicates the completion status taken from the SCUs
* completion code. It indicates the completion result for the SCU hardware.
*/
u32 scu_status;
/**
* This field indicates the completion status returned to the SCI user. It
* indicates the users view of the io request completion.
*/
u32 sci_status;
/**
* This field contains the value to be utilized when posting (e.g. Post_TC,
* Post_TC_Abort) this request to the silicon.
*/
u32 post_context;
void *command_buffer;
void *response_buffer;
struct scu_task_context *task_context_buffer;
struct scu_sgl_element_pair *sgl_element_pair_buffer;
/**
* This field indicates if this request is a task management request or
* normal IO request.
*/
bool is_task_management_request;
/**
* This field indicates that this request contains an initialized started
* substate machine.
*/
bool has_started_substate_machine;
/**
* This field is a pointer to the stored rx frame data. It is used in STP
* internal requests and SMP response frames. If this field is non-NULL the
* saved frame must be released on IO request completion.
*
* @todo In the future do we want to keep a list of RX frame buffers?
*/
u32 saved_rx_frame_index;
/**
* This field specifies the data necessary to manage the sub-state
* machine executed while in the SCI_BASE_REQUEST_STATE_STARTED state.
*/
struct sci_base_state_machine started_substate_machine;
/**
* This field specifies the current state handlers in place for this
* IO Request object. This field is updated each time the request
* changes state.
*/
const struct scic_sds_io_request_state_handler *state_handlers;
/**
* This field in the recorded device sequence for the io request. This is
* recorded during the build operation and is compared in the start
* operation. If the sequence is different then there was a change of
* devices from the build to start operations.
*/
u8 device_sequence;
};
typedef enum sci_status
(*scic_sds_io_request_frame_handler_t)(struct scic_sds_request *req, u32 frame);
typedef enum sci_status
(*scic_sds_io_request_event_handler_t)(struct scic_sds_request *req, u32 event);
typedef enum sci_status
(*scic_sds_io_request_task_completion_handler_t)(struct scic_sds_request *req, u32 completion_code);
/**
* struct scic_sds_io_request_state_handler - This is the SDS core definition
* of the state handlers.
*
*
*/
struct scic_sds_io_request_state_handler {
struct sci_base_request_state_handler parent;
scic_sds_io_request_task_completion_handler_t tc_completion_handler;
scic_sds_io_request_event_handler_t event_handler;
scic_sds_io_request_frame_handler_t frame_handler;
};
extern const struct sci_base_state scic_sds_request_state_table[];
extern const struct scic_sds_io_request_state_handler scic_sds_request_state_handler_table[];
extern const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[];
extern const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[];
extern const struct sci_base_state scic_sds_smp_request_started_substate_table[];
extern const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[];
/**
*
*
* This macro returns the maximum number of SGL element paris that we will
* support in a single IO request.
*/
#define SCU_MAX_SGL_ELEMENT_PAIRS ((SCU_IO_REQUEST_SGE_COUNT + 1) / 2)
/**
* scic_sds_request_get_controller() -
*
* This macro will return the controller for this io request object
*/
#define scic_sds_request_get_controller(this_request) \
((this_request)->owning_controller)
/**
* scic_sds_request_get_device() -
*
* This macro will return the device for this io request object
*/
#define scic_sds_request_get_device(this_request) \
((this_request)->target_device)
/**
* scic_sds_request_get_port() -
*
* This macro will return the port for this io request object
*/
#define scic_sds_request_get_port(this_request) \
scic_sds_remote_device_get_port(scic_sds_request_get_device(this_request))
/**
* scic_sds_request_get_post_context() -
*
* This macro returns the constructed post context result for the io request.
*/
#define scic_sds_request_get_post_context(this_request) \
((this_request)->post_context)
/**
* scic_sds_request_get_task_context() -
*
* This is a helper macro to return the os handle for this request object.
*/
#define scic_sds_request_get_task_context(request) \
((request)->task_context_buffer)
#define CACHE_LINE_SIZE (64)
#define scic_sds_request_align_task_context_buffer(address) \
((struct scu_task_context *)(\
(((unsigned long)(address)) + (CACHE_LINE_SIZE - 1)) \
& ~(CACHE_LINE_SIZE - 1) \
))
/**
* scic_sds_request_align_sgl_element_buffer() -
*
* This macro will align the memory address so that it is correct for the SCU
* hardware to DMA the SGL element pairs.
*/
#define scic_sds_request_align_sgl_element_buffer(address) \
((struct scu_sgl_element_pair *)(\
((char *)(address)) \
+ (\
((~(unsigned long)(address)) + 1) \
& (sizeof(struct scu_sgl_element_pair) - 1) \
) \
))
/**
* scic_sds_request_set_status() -
*
* This macro will set the scu hardware status and sci request completion
* status for an io request.
*/
#define scic_sds_request_set_status(request, scu_status_code, sci_status_code) \
{ \
(request)->scu_status = (scu_status_code); \
(request)->sci_status = (sci_status_code); \
}
#define scic_sds_request_complete(a_request) \
((a_request)->state_handlers->parent.complete_handler(&(a_request)->parent))
/**
* scic_sds_io_request_tc_completion() -
*
* This macro invokes the core state task completion handler for the
* SCIC_SDS_IO_REQUEST_T object.
*/
#define scic_sds_io_request_tc_completion(this_request, completion_code) \
{ \
if (this_request->parent.state_machine.current_state_id \
== SCI_BASE_REQUEST_STATE_STARTED \
&& this_request->has_started_substate_machine \
== false) \
scic_sds_request_started_state_tc_completion_handler(this_request, completion_code); \
else \
this_request->state_handlers->tc_completion_handler(this_request, completion_code); \
}
/**
* SCU_SGL_ZERO() -
*
* This macro zeros the hardware SGL element data
*/
#define SCU_SGL_ZERO(scu_sge) \
{ \
(scu_sge).length = 0; \
(scu_sge).address_lower = 0; \
(scu_sge).address_upper = 0; \
(scu_sge).address_modifier = 0; \
}
/**
* SCU_SGL_COPY() -
*
* This macro copys the SGL Element data from the host os to the hardware SGL
* elment data
*/
#define SCU_SGL_COPY(os_handle, scu_sge, os_sge) \
{ \
(scu_sge).length = \
scic_cb_sge_get_length_field(os_handle, os_sge); \
(scu_sge).address_upper = \
upper_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
(scu_sge).address_lower = \
lower_32_bits(scic_cb_sge_get_address_field(os_handle, os_sge)); \
(scu_sge).address_modifier = 0; \
}
/*
* *****************************************************************************
* * CORE REQUEST PROTOTYPES
* ***************************************************************************** */
void scic_sds_request_build_sgl(
struct scic_sds_request *this_request);
void scic_sds_stp_request_assign_buffers(
struct scic_sds_request *this_request);
void scic_sds_smp_request_assign_buffers(
struct scic_sds_request *this_request);
/* --------------------------------------------------------------------------- */
enum sci_status scic_sds_request_start(
struct scic_sds_request *this_request);
enum sci_status scic_sds_io_request_terminate(
struct scic_sds_request *this_request);
enum sci_status scic_sds_io_request_complete(
struct scic_sds_request *this_request);
void scic_sds_io_request_copy_response(
struct scic_sds_request *this_request);
enum sci_status scic_sds_io_request_event_handler(
struct scic_sds_request *this_request,
u32 event_code);
enum sci_status scic_sds_io_request_frame_handler(
struct scic_sds_request *this_request,
u32 frame_index);
enum sci_status scic_sds_task_request_terminate(
struct scic_sds_request *this_request);
/*
* *****************************************************************************
* * DEFAULT STATE HANDLERS
* ***************************************************************************** */
enum sci_status scic_sds_request_default_start_handler(
struct sci_base_request *this_request);
enum sci_status scic_sds_request_default_complete_handler(
struct sci_base_request *this_request);
enum sci_status scic_sds_request_default_destruct_handler(
struct sci_base_request *this_request);
enum sci_status scic_sds_request_default_tc_completion_handler(
struct scic_sds_request *this_request,
u32 completion_code);
enum sci_status scic_sds_request_default_event_handler(
struct scic_sds_request *this_request,
u32 event_code);
enum sci_status scic_sds_request_default_frame_handler(
struct scic_sds_request *this_request,
u32 frame_index);
/*
* *****************************************************************************
* * STARTED STATE HANDLERS
* ***************************************************************************** */
enum sci_status scic_sds_request_started_state_abort_handler(
struct sci_base_request *this_request);
enum sci_status scic_sds_request_started_state_tc_completion_handler(
struct scic_sds_request *this_request,
u32 completion_code);
#endif /* _SCIC_SDS_IO_REQUEST_H_ */

View File

@ -0,0 +1,410 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains This file contains the ready substate handlers for a SMP
* device.
*
*
*/
#include "sci_environment.h"
#include "scic_user_callback.h"
#include "scic_sds_remote_device.h"
#include "scic_sds_controller.h"
#include "scic_sds_port.h"
#include "scic_sds_request.h"
#include "scu_event_codes.h"
#include "scu_task_context.h"
/*
* *****************************************************************************
* * SMP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
* ***************************************************************************** */
/**
*
* @[in]: device The device the io is sent to.
* @[in]: request The io to start.
*
* This method will handle the start io operation for a SMP device that is in
* the idle state. enum sci_status
*/
static enum sci_status scic_sds_smp_remote_device_ready_idle_substate_start_io_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
enum sci_status status;
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
struct scic_sds_request *io_request = (struct scic_sds_request *)request;
/* Will the port allow the io request to start? */
status = this_device->owning_port->state_handlers->start_io_handler(
this_device->owning_port,
this_device,
io_request
);
if (status == SCI_SUCCESS) {
status =
scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
if (status == SCI_SUCCESS) {
status = scic_sds_request_start(io_request);
}
if (status == SCI_SUCCESS) {
this_device->working_request = io_request;
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
);
}
scic_sds_remote_device_start_request(this_device, io_request, status);
}
return status;
}
/*
* ******************************************************************************
* * SMP REMOTE DEVICE READY SUBSTATE CMD HANDLERS
* ****************************************************************************** */
/**
*
* @device: This is the device object that is receiving the IO.
* @request: The io to start.
*
* This device is already handling a command it can not accept new commands
* until this one is complete. enum sci_status
*/
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
return SCI_FAILURE_INVALID_STATE;
}
/**
* this is the complete_io_handler for smp device at ready cmd substate.
* @device: This is the device object that is receiving the IO.
* @request: The io to start.
*
* enum sci_status
*/
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
enum sci_status status;
struct scic_sds_remote_device *this_device;
struct scic_sds_request *the_request;
this_device = (struct scic_sds_remote_device *)device;
the_request = (struct scic_sds_request *)request;
status = scic_sds_io_request_complete(the_request);
if (status == SCI_SUCCESS) {
status = scic_sds_port_complete_io(
this_device->owning_port, this_device, the_request);
if (status == SCI_SUCCESS) {
scic_sds_remote_device_decrement_request_count(this_device);
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
);
} else
dev_err(scirdev_to_dev(this_device),
"%s: SCIC SDS Remote Device 0x%p io request "
"0x%p could not be completd on the port 0x%p "
"failed with status %d.\n",
__func__,
this_device,
the_request,
this_device->owning_port,
status);
}
return status;
}
/**
* This is frame handler for smp device ready cmd substate.
* @this_device: This is the device object that is receiving the frame.
* @frame_index: The index for the frame received.
*
* enum sci_status
*/
static enum sci_status scic_sds_smp_remote_device_ready_cmd_substate_frame_handler(
struct scic_sds_remote_device *this_device,
u32 frame_index)
{
enum sci_status status;
/*
* / The device does not process any UF received from the hardware while
* / in this state. All unsolicited frames are forwarded to the io request
* / object. */
status = scic_sds_io_request_frame_handler(
this_device->working_request,
frame_index
);
return status;
}
/* --------------------------------------------------------------------------- */
struct scic_sds_remote_device_state_handler
scic_sds_smp_remote_device_ready_substate_handler_table[
SCIC_SDS_SMP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
{
/* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_default_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_smp_remote_device_ready_idle_substate_start_io_handler,
scic_sds_remote_device_default_complete_request_handler,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_remote_device_default_start_request_handler,
scic_sds_remote_device_default_complete_request_handler
},
scic_sds_remote_device_default_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_remote_device_general_event_handler,
scic_sds_remote_device_default_frame_handler
},
/* SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_default_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_smp_remote_device_ready_cmd_substate_start_io_handler,
scic_sds_smp_remote_device_ready_cmd_substate_complete_io_handler,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_remote_device_default_start_request_handler,
scic_sds_remote_device_default_complete_request_handler
},
scic_sds_remote_device_default_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_remote_device_general_event_handler,
scic_sds_smp_remote_device_ready_cmd_substate_frame_handler
}
};
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the enter and exit functions for the
* struct scic_sds_remote_device ready substate machine.
*
*
*/
#include "scic_remote_device.h"
#include "scic_user_callback.h"
#include "scic_sds_remote_device.h"
#include "scic_sds_controller.h"
#include "scic_sds_port.h"
#include "sci_util.h"
#include "sci_environment.h"
/**
*
* @object: This is the struct sci_base_object which is cast into a
* struct scic_sds_remote_device.
*
* This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE enter method.
* This method sets the ready cmd substate handlers and reports the device as
* ready. none
*/
static void scic_sds_smp_remote_device_ready_idle_substate_enter(
struct sci_base_object *object)
{
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
SET_STATE_HANDLER(
this_device,
scic_sds_smp_remote_device_ready_substate_handler_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
);
scic_cb_remote_device_ready(
scic_sds_remote_device_get_controller(this_device), this_device);
}
/**
*
* @object: This is the struct sci_base_object which is cast into a
* struct scic_sds_remote_device.
*
* This is the SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD enter method. This
* method sets the remote device objects ready cmd substate handlers, and
* notify core user that the device is not ready. none
*/
static void scic_sds_smp_remote_device_ready_cmd_substate_enter(
struct sci_base_object *object)
{
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
BUG_ON(this_device->working_request == NULL);
SET_STATE_HANDLER(
this_device,
scic_sds_smp_remote_device_ready_substate_handler_table,
SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD
);
scic_cb_remote_device_not_ready(
scic_sds_remote_device_get_controller(this_device),
this_device,
SCIC_REMOTE_DEVICE_NOT_READY_SMP_REQUEST_STARTED
);
}
/**
*
* @object: This is the struct sci_base_object which is cast into a
* struct scic_sds_remote_device.
*
* This is the SCIC_SDS_SSP_REMOTE_DEVICE_READY_SUBSTATE_CMD exit method. none
*/
static void scic_sds_smp_remote_device_ready_cmd_substate_exit(
struct sci_base_object *object)
{
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)object;
this_device->working_request = NULL;
}
/* --------------------------------------------------------------------------- */
const struct sci_base_state scic_sds_smp_remote_device_ready_substate_table[] = {
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.enter_state = scic_sds_smp_remote_device_ready_idle_substate_enter,
},
[SCIC_SDS_SMP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.enter_state = scic_sds_smp_remote_device_ready_cmd_substate_enter,
.exit_state = scic_sds_smp_remote_device_ready_cmd_substate_exit,
},
};

View File

@ -0,0 +1,669 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "intel_sas.h"
#include "sci_base_state_machine.h"
#include "scic_controller.h"
#include "scic_remote_device.h"
#include "scic_sds_controller.h"
#include "scic_sds_remote_device.h"
#include "scic_sds_request.h"
#include "scic_sds_smp_request.h"
#include "sci_environment.h"
#include "sci_util.h"
#include "scu_completion_codes.h"
#include "scu_task_context.h"
static void scu_smp_request_construct_task_context(
struct scic_sds_request *this_request,
struct smp_request *smp_request);
/**
*
*
* This method return the memory space required for STP PIO requests. u32
*/
u32 scic_sds_smp_request_get_object_size(void)
{
return sizeof(struct scic_sds_request)
+ sizeof(struct smp_request)
+ sizeof(struct smp_response)
+ sizeof(struct scu_task_context);
}
/**
* scic_sds_smp_request_get_command_buffer() -
*
* This macro returns the address of the smp command buffer in the smp request
* memory. No need to cast to SMP request type.
*/
#define scic_sds_smp_request_get_command_buffer(memory) \
(((char *)(memory)) + sizeof(struct scic_sds_request))
/**
* scic_sds_smp_request_get_response_buffer() -
*
* This macro returns the address of the smp response buffer in the smp request
* memory.
*/
#define scic_sds_smp_request_get_response_buffer(memory) \
(((char *)(scic_sds_smp_request_get_command_buffer(memory))) \
+ sizeof(struct smp_request))
/**
* scic_sds_smp_request_get_task_context_buffer() -
*
* This macro returs the task context buffer for the SMP request.
*/
#define scic_sds_smp_request_get_task_context_buffer(memory) \
((struct scu_task_context *)(\
((char *)(scic_sds_smp_request_get_response_buffer(memory))) \
+ sizeof(struct smp_response) \
))
/**
* This method build the remainder of the IO request object.
* @this_request: This parameter specifies the request object being constructed.
*
* The scic_sds_general_request_construct() must be called before this call is
* valid. none
*/
void scic_sds_smp_request_assign_buffers(
struct scic_sds_request *this_request)
{
/* Assign all of the buffer pointers */
this_request->command_buffer =
scic_sds_smp_request_get_command_buffer(this_request);
this_request->response_buffer =
scic_sds_smp_request_get_response_buffer(this_request);
this_request->sgl_element_pair_buffer = NULL;
if (this_request->was_tag_assigned_by_user == false) {
this_request->task_context_buffer =
scic_sds_smp_request_get_task_context_buffer(this_request);
this_request->task_context_buffer =
scic_sds_request_align_task_context_buffer(this_request->task_context_buffer);
}
}
/**
* This method is called by the SCI user to build an SMP IO request.
*
* - The user must have previously called scic_io_request_construct() on the
* supplied IO request. Indicate if the controller successfully built the IO
* request. SCI_SUCCESS This value is returned if the IO request was
* successfully built. SCI_FAILURE_UNSUPPORTED_PROTOCOL This value is returned
* if the remote_device does not support the SMP protocol.
* SCI_FAILURE_INVALID_ASSOCIATION This value is returned if the user did not
* properly set the association between the SCIC IO request and the user's IO
* request. Please refer to the sci_object_set_association() routine for more
* information.
*/
enum sci_status scic_io_request_construct_smp(
struct scic_sds_request *sci_req)
{
struct smp_request *smp_req = kmalloc(sizeof(*smp_req), GFP_KERNEL);
if (!smp_req)
return SCI_FAILURE_INSUFFICIENT_RESOURCES;
sci_req->protocol = SCIC_SMP_PROTOCOL;
sci_req->has_started_substate_machine = true;
/* Construct the started sub-state machine. */
sci_base_state_machine_construct(
&sci_req->started_substate_machine,
&sci_req->parent.parent,
scic_sds_smp_request_started_substate_table,
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
);
/* Construct the SMP SCU Task Context */
memcpy(smp_req, sci_req->command_buffer, sizeof(*smp_req));
/*
* Look at the SMP requests' header fields; for certain SAS 1.x SMP
* functions under SAS 2.0, a zero request length really indicates
* a non-zero default length. */
if (smp_req->header.request_length == 0) {
switch (smp_req->header.function) {
case SMP_FUNCTION_DISCOVER:
case SMP_FUNCTION_REPORT_PHY_ERROR_LOG:
case SMP_FUNCTION_REPORT_PHY_SATA:
case SMP_FUNCTION_REPORT_ROUTE_INFORMATION:
smp_req->header.request_length = 2;
break;
case SMP_FUNCTION_CONFIGURE_ROUTE_INFORMATION:
case SMP_FUNCTION_PHY_CONTROL:
case SMP_FUNCTION_PHY_TEST:
smp_req->header.request_length = 9;
break;
/* Default - zero is a valid default for 2.0. */
}
}
scu_smp_request_construct_task_context(sci_req, smp_req);
sci_base_state_machine_change_state(
&sci_req->parent.state_machine,
SCI_BASE_REQUEST_STATE_CONSTRUCTED
);
kfree(smp_req);
return SCI_SUCCESS;
}
/**
* This method is called by the SCI user to build an SMP pass-through IO
* request.
* @scic_smp_request: This parameter specifies the handle to the io request
* object to be built.
* @passthru_cb: This parameter specifies the pointer to the callback structure
* that contains the function pointers
*
* - The user must have previously called scic_io_request_construct() on the
* supplied IO request. Indicate if the controller successfully built the IO
* request.
*/
/**
* This method will fill in the SCU Task Context for a SMP request. The
* following important settings are utilized: -# task_type ==
* SCU_TASK_TYPE_SMP. This simply indicates that a normal request type
* (i.e. non-raw frame) is being utilized to perform task management. -#
* control_frame == 1. This ensures that the proper endianess is set so
* that the bytes are transmitted in the right order for a smp request frame.
* @this_request: This parameter specifies the smp request object being
* constructed.
*
*/
static void scu_smp_request_construct_task_context(
struct scic_sds_request *this_request,
struct smp_request *smp_request)
{
dma_addr_t physical_address;
struct scic_sds_controller *owning_controller;
struct scic_sds_remote_device *target_device;
struct scic_sds_port *target_port;
struct scu_task_context *task_context;
/* byte swap the smp request. */
scic_word_copy_with_swap(
this_request->command_buffer,
(u32 *)smp_request,
sizeof(struct smp_request) / sizeof(u32)
);
task_context = scic_sds_request_get_task_context(this_request);
owning_controller = scic_sds_request_get_controller(this_request);
target_device = scic_sds_request_get_device(this_request);
target_port = scic_sds_request_get_port(this_request);
/*
* Fill in the TC with the its required data
* 00h */
task_context->priority = 0;
task_context->initiator_request = 1;
task_context->connection_rate =
scic_remote_device_get_connection_rate(target_device);
task_context->protocol_engine_index =
scic_sds_controller_get_protocol_engine_group(owning_controller);
task_context->logical_port_index =
scic_sds_port_get_index(target_port);
task_context->protocol_type = SCU_TASK_CONTEXT_PROTOCOL_SMP;
task_context->abort = 0;
task_context->valid = SCU_TASK_CONTEXT_VALID;
task_context->context_type = SCU_TASK_CONTEXT_TYPE;
/* 04h */
task_context->remote_node_index = this_request->target_device->rnc->remote_node_index;
task_context->command_code = 0;
task_context->task_type = SCU_TASK_TYPE_SMP_REQUEST;
/* 08h */
task_context->link_layer_control = 0;
task_context->do_not_dma_ssp_good_response = 1;
task_context->strict_ordering = 0;
task_context->control_frame = 1;
task_context->timeout_enable = 0;
task_context->block_guard_enable = 0;
/* 0ch */
task_context->address_modifier = 0;
/* 10h */
task_context->ssp_command_iu_length = smp_request->header.request_length;
/* 14h */
task_context->transfer_length_bytes = 0;
/*
* 18h ~ 30h, protocol specific
* since commandIU has been build by framework at this point, we just
* copy the frist DWord from command IU to this location. */
memcpy((void *)(&task_context->type.smp), this_request->command_buffer, sizeof(u32));
/*
* 40h
* "For SMP you could program it to zero. We would prefer that way so that
* done code will be consistent." - Venki */
task_context->task_phase = 0;
if (this_request->was_tag_assigned_by_user) {
/* Build the task context now since we have already read the data */
this_request->post_context = (
SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
| (
scic_sds_controller_get_protocol_engine_group(owning_controller)
<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
)
| (
scic_sds_port_get_index(target_port)
<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
)
| scic_sds_io_tag_get_index(this_request->io_tag)
);
} else {
/* Build the task context now since we have already read the data */
this_request->post_context = (
SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC
| (
scic_sds_controller_get_protocol_engine_group(owning_controller)
<< SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT
)
| (
scic_sds_port_get_index(target_port)
<< SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT
)
/* This is not assigned because we have to wait until we get a TCi */
);
}
/*
* Copy the physical address for the command buffer to the SCU Task Context
* command buffer should not contain command header. */
scic_cb_io_request_get_physical_address(
scic_sds_request_get_controller(this_request),
this_request,
((char *)(this_request->command_buffer) + sizeof(u32)),
&physical_address
);
task_context->command_iu_upper =
upper_32_bits(physical_address);
task_context->command_iu_lower =
lower_32_bits(physical_address);
/* SMP response comes as UF, so no need to set response IU address. */
task_context->response_iu_upper = 0;
task_context->response_iu_lower = 0;
}
/**
* This method processes an unsolicited frame while the SMP request is waiting
* for a response frame. It will copy the response data, release the
* unsolicited frame, and transition the request to the
* SCI_BASE_REQUEST_STATE_COMPLETED state.
* @this_request: This parameter specifies the request for which the
* unsolicited frame was received.
* @frame_index: This parameter indicates the unsolicited frame index that
* should contain the response.
*
* This method returns an indication of whether the response frame was handled
* successfully or not. SCI_SUCCESS Currently this value is always returned and
* indicates successful processing of the TC response.
*/
static enum sci_status scic_sds_smp_request_await_response_frame_handler(
struct scic_sds_request *this_request,
u32 frame_index)
{
enum sci_status status;
void *frame_header;
struct smp_response_header *this_frame_header;
u8 *user_smp_buffer = this_request->response_buffer;
status = scic_sds_unsolicited_frame_control_get_header(
&(scic_sds_request_get_controller(this_request)->uf_control),
frame_index,
&frame_header
);
/* byte swap the header. */
scic_word_copy_with_swap(
(u32 *)user_smp_buffer,
frame_header,
sizeof(struct smp_response_header) / sizeof(u32)
);
this_frame_header = (struct smp_response_header *)user_smp_buffer;
if (this_frame_header->smp_frame_type == SMP_FRAME_TYPE_RESPONSE) {
void *smp_response_buffer;
status = scic_sds_unsolicited_frame_control_get_buffer(
&(scic_sds_request_get_controller(this_request)->uf_control),
frame_index,
&smp_response_buffer
);
scic_word_copy_with_swap(
(u32 *)(user_smp_buffer + sizeof(struct smp_response_header)),
smp_response_buffer,
sizeof(union smp_response_body) / sizeof(u32)
);
if (this_frame_header->function == SMP_FUNCTION_DISCOVER) {
struct smp_response *this_smp_response;
this_smp_response = (struct smp_response *)user_smp_buffer;
/*
* Some expanders only report an attached SATA device, and
* not an STP target. Since the core depends on the STP
* target attribute to correctly build I/O, set the bit now
* if necessary. */
if (this_smp_response->response.discover.protocols.u.bits.attached_sata_device
&& !this_smp_response->response.discover.protocols.u.bits.attached_stp_target) {
this_smp_response->response.discover.protocols.u.bits.attached_stp_target = 1;
dev_dbg(scic_to_dev(this_request->owning_controller),
"%s: scic_sds_smp_request_await_response_frame_handler(0x%p) Found SATA dev, setting STP bit.\n",
__func__, this_request);
}
}
/*
* Don't need to copy to user space. User instead will refer to
* core request's response buffer. */
/*
* copy the smp response to framework smp request's response buffer.
* scic_sds_smp_request_copy_response(this_request); */
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
sci_base_state_machine_change_state(
&this_request->started_substate_machine,
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
);
} else {
/* This was not a response frame why did it get forwarded? */
dev_err(scic_to_dev(this_request->owning_controller),
"%s: SCIC SMP Request 0x%p received unexpected frame "
"%d type 0x%02x\n",
__func__,
this_request,
frame_index,
this_frame_header->smp_frame_type);
scic_sds_request_set_status(
this_request,
SCU_TASK_DONE_SMP_FRM_TYPE_ERR,
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
}
scic_sds_controller_release_frame(
this_request->owning_controller, frame_index
);
return SCI_SUCCESS;
}
/**
* This method processes an abnormal TC completion while the SMP request is
* waiting for a response frame. It decides what happened to the IO based
* on TC completion status.
* @this_request: This parameter specifies the request for which the TC
* completion was received.
* @completion_code: This parameter indicates the completion status information
* for the TC.
*
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
* this method always returns success.
*/
static enum sci_status scic_sds_smp_request_await_response_tc_completion_handler(
struct scic_sds_request *this_request,
u32 completion_code)
{
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
/*
* In the AWAIT RESPONSE state, any TC completion is unexpected.
* but if the TC has success status, we complete the IO anyway. */
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_RESP_TO_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_UFI_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_FRM_TYPE_ERR):
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_SMP_LL_RX_ERR):
/*
* These status has been seen in a specific LSI expander, which sometimes
* is not able to send smp response within 2 ms. This causes our hardware
* break the connection and set TC completion with one of these SMP_XXX_XX_ERR
* status. For these type of error, we ask scic user to retry the request. */
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_SMP_RESP_TO_ERR, SCI_FAILURE_RETRY_REQUIRED
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
default:
/*
* All other completion status cause the IO to be complete. If a NAK
* was received, then it is up to the user to retry the request. */
scic_sds_request_set_status(
this_request,
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
}
return SCI_SUCCESS;
}
/**
* This method processes the completions transport layer (TL) status to
* determine if the SMP request was sent successfully. If the SMP request
* was sent successfully, then the state for the SMP request transits to
* waiting for a response frame.
* @this_request: This parameter specifies the request for which the TC
* completion was received.
* @completion_code: This parameter indicates the completion status information
* for the TC.
*
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
* this method always returns success.
*/
static enum sci_status scic_sds_smp_request_await_tc_completion_tc_completion_handler(
struct scic_sds_request *this_request,
u32 completion_code)
{
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
default:
/*
* All other completion status cause the IO to be complete. If a NAK
* was received, then it is up to the user to retry the request. */
scic_sds_request_set_status(
this_request,
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
}
return SCI_SUCCESS;
}
const struct scic_sds_io_request_state_handler scic_sds_smp_request_started_substate_handler_table[] = {
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
.tc_completion_handler = scic_sds_smp_request_await_response_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_smp_request_await_response_frame_handler,
},
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
.tc_completion_handler = scic_sds_smp_request_await_tc_completion_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_request_default_frame_handler,
}
};
/**
* This method performs the actions required when entering the
* SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
* includes setting the IO request state handlers for this sub-state.
* @object: This parameter specifies the request object for which the sub-state
* change is occuring.
*
* none.
*/
static void scic_sds_smp_request_started_await_response_substate_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_smp_request_started_substate_handler_table,
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE
);
}
/**
* This method performs the actions required when entering the
* SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION sub-state.
* This includes setting the SMP request state handlers for this sub-state.
* @object: This parameter specifies the request object for which the sub-state
* change is occuring.
*
* none.
*/
static void scic_sds_smp_request_started_await_tc_completion_substate_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_smp_request_started_substate_handler_table,
SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION
);
}
const struct sci_base_state scic_sds_smp_request_started_substate_table[] = {
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_RESPONSE] = {
.enter_state = scic_sds_smp_request_started_await_response_substate_enter,
},
[SCIC_SDS_SMP_REQUEST_STARTED_SUBSTATE_AWAIT_TC_COMPLETION] = {
.enter_state = scic_sds_smp_request_started_await_tc_completion_substate_enter,
},
};

View File

@ -0,0 +1,70 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_SMP_REQUEST_T_
#define _SCIC_SDS_SMP_REQUEST_T_
#include "intel_sas.h"
#include "sci_types.h"
#include "scic_sds_request.h"
u32 scic_sds_smp_request_get_object_size(void);
void scic_sds_smp_request_copy_response(
struct scic_sds_request *this_request);
#endif /* _SCIC_SDS_SMP_REQUEST_T_ */

View File

@ -0,0 +1,340 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the task management substate handlers for the
* SCIC_SDS_IO_REQUEST object.
*
*
*/
#include "intel_sas.h"
#include "sci_environment.h"
#include "scic_sds_request.h"
#include "scic_controller.h"
#include "scic_sds_controller.h"
#include "scu_completion_codes.h"
#include "scu_task_context.h"
/**
* This method processes the completions transport layer (TL) status to
* determine if the RAW task management frame was sent successfully. If the
* raw frame was sent successfully, then the state for the task request
* transitions to waiting for a response frame.
* @this_request: This parameter specifies the request for which the TC
* completion was received.
* @completion_code: This parameter indicates the completion status information
* for the TC.
*
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
* this method always returns success.
*/
static enum sci_status scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler(
struct scic_sds_request *this_request,
u32 completion_code)
{
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
sci_base_state_machine_change_state(
&this_request->started_substate_machine,
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
);
break;
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_ACK_NAK_TO):
/*
* Currently, the decision is to simply allow the task request to
* timeout if the task IU wasn't received successfully.
* There is a potential for receiving multiple task responses if we
* decide to send the task IU again. */
dev_warn(scic_to_dev(this_request->owning_controller),
"%s: TaskRequest:0x%p CompletionCode:%x - "
"ACK/NAK timeout\n",
__func__,
this_request,
completion_code);
sci_base_state_machine_change_state(
&this_request->started_substate_machine,
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
);
break;
default:
/*
* All other completion status cause the IO to be complete. If a NAK
* was received, then it is up to the user to retry the request. */
scic_sds_request_set_status(
this_request,
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
}
return SCI_SUCCESS;
}
/**
* This method is responsible for processing a terminate/abort request for this
* TC while the request is waiting for the task management response
* unsolicited frame.
* @this_request: This parameter specifies the request for which the
* termination was requested.
*
* This method returns an indication as to whether the abort request was
* successfully handled. need to update to ensure the received UF doesn't cause
* damage to subsequent requests (i.e. put the extended tag in a holding
* pattern for this particular device).
*/
static enum sci_status scic_sds_ssp_task_request_await_tc_response_abort_handler(
struct sci_base_request *request)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)request;
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_ABORTING
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
return SCI_SUCCESS;
}
/**
* This method processes an unsolicited frame while the task mgmt request is
* waiting for a response frame. It will copy the response data, release
* the unsolicited frame, and transition the request to the
* SCI_BASE_REQUEST_STATE_COMPLETED state.
* @this_request: This parameter specifies the request for which the
* unsolicited frame was received.
* @frame_index: This parameter indicates the unsolicited frame index that
* should contain the response.
*
* This method returns an indication of whether the TC response frame was
* handled successfully or not. SCI_SUCCESS Currently this value is always
* returned and indicates successful processing of the TC response. Should
* probably update to check frame type and make sure it is a response frame.
*/
static enum sci_status scic_sds_ssp_task_request_await_tc_response_frame_handler(
struct scic_sds_request *this_request,
u32 frame_index)
{
scic_sds_io_request_copy_response(this_request);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
scic_sds_controller_release_frame(
this_request->owning_controller, frame_index
);
return SCI_SUCCESS;
}
const struct scic_sds_io_request_state_handler scic_sds_ssp_task_request_started_substate_handler_table[] = {
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
.tc_completion_handler = scic_sds_ssp_task_request_await_tc_completion_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_request_default_frame_handler,
},
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_ssp_task_request_await_tc_response_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler,
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_ssp_task_request_await_tc_response_frame_handler,
}
};
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the enter/exit methods associated with each of the task
* management raw request states. For more information on the task
* management request state machine please refer to scic_sds_io_request.h
*
*
*/
#include "scic_sds_request.h"
#include "sci_base_state_machine.h"
/**
* This method performs the actions required when entering the
* SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
* sub-state. This includes setting the IO request state handlers for this
* sub-state.
* @object: This parameter specifies the request object for which the sub-state
* change is occuring.
*
* none.
*/
static void scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_ssp_task_request_started_substate_handler_table,
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION
);
}
/**
* This method performs the actions required when entering the
* SCIC_SDS_IO_REQUEST_STARTED_SUBSTATE_AWAIT_TC_RESPONSE sub-state. This
* includes setting the IO request state handlers for this sub-state.
* @object: This parameter specifies the request object for which the sub-state
* change is occuring.
*
* none.
*/
static void scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_ssp_task_request_started_substate_handler_table,
SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE
);
}
const struct sci_base_state scic_sds_io_request_started_task_mgmt_substate_table[] = {
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_COMPLETION] = {
.enter_state = scic_sds_io_request_started_task_mgmt_await_tc_completion_substate_enter,
},
[SCIC_SDS_IO_REQUEST_STARTED_TASK_MGMT_SUBSTATE_AWAIT_TC_RESPONSE] = {
.enter_state = scic_sds_io_request_started_task_mgmt_await_task_response_substate_enter,
},
};

View File

@ -0,0 +1,838 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(DISABLE_ATAPI)
#include "intel_ata.h"
#include "intel_sas.h"
#include "intel_sata.h"
#include "intel_sat.h"
#include "sati_translator_sequence.h"
#include "sci_base_state.h"
#include "scic_controller.h"
#include "scic_remote_device.h"
#include "scic_sds_controller.h"
#include "scic_sds_remote_device.h"
#include "scic_sds_request.h"
#include "scic_sds_stp_packet_request.h"
#include "scic_user_callback.h"
#include "sci_util.h"
#include "scu_completion_codes.h"
#include "scu_task_context.h"
/**
* This method will fill in the SCU Task Context for a PACKET fis. And
* construct the request STARTED sub-state machine for Packet Protocol IO.
* @this_request: This parameter specifies the stp packet request object being
* constructed.
*
*/
enum sci_status scic_sds_stp_packet_request_construct(
struct scic_sds_request *this_request)
{
struct sata_fis_reg_h2d *h2d_fis =
scic_stp_io_request_get_h2d_reg_address(
this_request
);
/*
* Work around, we currently only support PACKET DMA protocol, so we
* need to make change to Packet Fis features field. */
h2d_fis->features = h2d_fis->features | ATA_PACKET_FEATURE_DMA;
scic_sds_stp_non_ncq_request_construct(this_request);
/* Build the Packet Fis task context structure */
scu_stp_raw_request_construct_task_context(
(struct scic_sds_stp_request *)this_request,
this_request->task_context_buffer
);
sci_base_state_machine_construct(
&this_request->started_substate_machine,
&this_request->parent.parent,
scic_sds_stp_packet_request_started_substate_table,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
);
return SCI_SUCCESS;
}
/**
* This method will fill in the SCU Task Context for a Packet request command
* phase in PACKET DMA DATA (IN/OUT) type. The following important settings
* are utilized: -# task_type == SCU_TASK_TYPE_PACKET_DMA. This simply
* indicates that a normal request type (i.e. non-raw frame) is being
* utilized to perform task management. -# control_frame == 1. This ensures
* that the proper endianess is set so that the bytes are transmitted in the
* right order for a smp request frame.
* @this_request: This parameter specifies the smp request object being
* constructed.
* @task_context: The task_context to be reconstruct for packet request command
* phase.
*
*/
void scu_stp_packet_request_command_phase_construct_task_context(
struct scic_sds_request *this_request,
struct scu_task_context *task_context)
{
void *atapi_cdb;
u32 atapi_cdb_length;
struct scic_sds_stp_request *stp_request = (struct scic_sds_stp_request *)this_request;
/*
* reference: SSTL 1.13.4.2
* task_type, sata_direction */
if (scic_cb_io_request_get_data_direction(this_request->user_request)
== SCI_IO_REQUEST_DATA_OUT) {
task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_OUT;
task_context->sata_direction = 0;
} else { /* todo: for NO_DATA command, we need to send out raw frame. */
task_context->task_type = SCU_TASK_TYPE_PACKET_DMA_IN;
task_context->sata_direction = 1;
}
/* sata header */
memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
/*
* Copy in the command IU with CDB so that the commandIU address doesn't
* change. */
memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
atapi_cdb =
scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
atapi_cdb_length =
scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length);
atapi_cdb_length =
max(atapi_cdb_length, stp_request->type.packet.device_preferred_cdb_length);
task_context->ssp_command_iu_length =
((atapi_cdb_length % 4) == 0) ?
(atapi_cdb_length / 4) : ((atapi_cdb_length / 4) + 1);
/* task phase is set to TX_CMD */
task_context->task_phase = 0x1;
/* retry counter */
task_context->stp_retry_count = 0;
if (scic_cb_request_is_initial_construction(this_request->user_request)) {
/* data transfer size. */
task_context->transfer_length_bytes =
scic_cb_io_request_get_transfer_length(this_request->user_request);
/* setup sgl */
scic_sds_request_build_sgl(this_request);
} else {
/* data transfer size, need to be 4 bytes aligned. */
task_context->transfer_length_bytes = (SCSI_FIXED_SENSE_DATA_BASE_LENGTH + 2);
scic_sds_stp_packet_internal_request_sense_build_sgl(this_request);
}
}
/**
* This method will fill in the SCU Task Context for a DATA fis containing CDB
* in Raw Frame type. The TC for previous Packet fis was already there, we
* only need to change the H2D fis content.
* @this_request: This parameter specifies the smp request object being
* constructed.
* @task_context: The task_context to be reconstruct for packet request command
* phase.
*
*/
void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
struct scic_sds_request *this_request,
struct scu_task_context *task_context)
{
void *atapi_cdb =
scic_cb_stp_packet_io_request_get_cdb_address(this_request->user_request);
u32 atapi_cdb_length =
scic_cb_stp_packet_io_request_get_cdb_length(this_request->user_request);
memset(this_request->command_buffer, 0, sizeof(struct sata_fis_reg_h2d));
memcpy(((u8 *)this_request->command_buffer + sizeof(u32)), atapi_cdb, atapi_cdb_length);
memset(&(task_context->type.stp), 0, sizeof(struct STP_TASK_CONTEXT));
task_context->type.stp.fis_type = SATA_FIS_TYPE_DATA;
/*
* Note the data send out has to be 4 bytes aligned. Or else out hardware will
* patch non-zero bytes and cause the target device unhappy. */
task_context->transfer_length_bytes = 12;
}
/*
* *@brief This methods decode the D2H status FIS and retrieve the sense data,
* then pass the sense data to user request.
*
***@param[in] this_request The request receive D2H status FIS.
***@param[in] status_fis The D2H status fis to be processed.
*
*/
enum sci_status scic_sds_stp_packet_request_process_status_fis(
struct scic_sds_request *this_request,
struct sata_fis_reg_d2h *status_fis)
{
enum sci_status status = SCI_SUCCESS;
/* TODO: Process the error status fis, retrieve sense data. */
if (status_fis->status & ATA_STATUS_REG_ERROR_BIT)
status = SCI_FAILURE_IO_RESPONSE_VALID;
return status;
}
/*
* *@brief This methods builds sgl for internal REQUEST SENSE stp packet
* command using this request response buffer, only one sge is
* needed.
*
***@param[in] this_request The request receive request sense data.
*
*/
void scic_sds_stp_packet_internal_request_sense_build_sgl(
struct scic_sds_request *this_request)
{
void *sge;
struct scu_sgl_element_pair *scu_sgl_list = NULL;
struct scu_task_context *task_context;
dma_addr_t physical_address;
struct sci_ssp_response_iu *rsp_iu =
(struct sci_ssp_response_iu *)this_request->response_buffer;
sge = (void *)&rsp_iu->data[0];
task_context = (struct scu_task_context *)this_request->task_context_buffer;
scu_sgl_list = &task_context->sgl_pair_ab;
scic_cb_io_request_get_physical_address(
scic_sds_request_get_controller(this_request),
this_request,
((char *)sge),
&physical_address
);
scu_sgl_list->A.address_upper = sci_cb_physical_address_upper(physical_address);
scu_sgl_list->A.address_lower = sci_cb_physical_address_lower(physical_address);
scu_sgl_list->A.length = task_context->transfer_length_bytes;
scu_sgl_list->A.address_modifier = 0;
SCU_SGL_ZERO(scu_sgl_list->B);
}
/**
* This method processes the completions transport layer (TL) status to
* determine if the Packet FIS was sent successfully. If the Packet FIS was
* sent successfully, then the state for the Packet request transits to
* waiting for a PIO SETUP frame.
* @this_request: This parameter specifies the request for which the TC
* completion was received.
* @completion_code: This parameter indicates the completion status information
* for the TC.
*
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
* this method always returns success.
*/
enum sci_status scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler(
struct scic_sds_request *this_request,
u32 completion_code)
{
enum sci_status status = SCI_SUCCESS;
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
case SCU_MAKE_COMPLETION_STATUS(SCU_TASK_DONE_GOOD):
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
sci_base_state_machine_change_state(
&this_request->started_substate_machine,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
);
break;
default:
/*
* All other completion status cause the IO to be complete. If a NAK
* was received, then it is up to the user to retry the request. */
scic_sds_request_set_status(
this_request,
SCU_NORMALIZE_COMPLETION_STATUS(completion_code),
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
}
return status;
}
/**
* This method processes an unsolicited frame while the Packet request is
* waiting for a PIO SETUP FIS. It will release the unsolicited frame, and
* transition the request to the COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
* state.
* @this_request: This parameter specifies the request for which the
* unsolicited frame was received.
* @frame_index: This parameter indicates the unsolicited frame index that
* should contain the response.
*
* This method returns an indication of whether the pio setup frame was handled
* successfully or not. SCI_SUCCESS Currently this value is always returned and
* indicates successful processing of the TC response.
*/
enum sci_status scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler(
struct scic_sds_request *request,
u32 frame_index)
{
enum sci_status status;
struct sata_fis_header *frame_header;
u32 *frame_buffer;
struct scic_sds_stp_request *this_request;
this_request = (struct scic_sds_stp_request *)request;
status = scic_sds_unsolicited_frame_control_get_header(
&(this_request->parent.owning_controller->uf_control),
frame_index,
(void **)&frame_header
);
if (status == SCI_SUCCESS) {
BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_PIO_SETUP);
/*
* Get from the frame buffer the PIO Setup Data, although we don't need
* any info from this pio setup fis. */
scic_sds_unsolicited_frame_control_get_buffer(
&(this_request->parent.owning_controller->uf_control),
frame_index,
(void **)&frame_buffer
);
/*
* Get the data from the PIO Setup
* The SCU Hardware returns first word in the frame_header and the rest
* of the data is in the frame buffer so we need to back up one dword */
this_request->type.packet.device_preferred_cdb_length =
(u16)((struct sata_fis_pio_setup *)(&frame_buffer[-1]))->transfter_count;
/* Frame has been decoded return it to the controller */
scic_sds_controller_release_frame(
this_request->parent.owning_controller, frame_index
);
sci_base_state_machine_change_state(
&this_request->parent.started_substate_machine,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
);
} else
dev_err(scic_to_dev(request->owning_controller),
"%s: SCIC IO Request 0x%p could not get frame header "
"for frame index %d, status %x\n",
__func__, this_request, frame_index, status);
return status;
}
/**
* This method processes the completions transport layer (TL) status to
* determine if the PACKET command data FIS was sent successfully. If
* successfully, then the state for the packet request transits to COMPLETE
* state. If not successfuly, the request transits to
* COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE.
* @this_request: This parameter specifies the request for which the TC
* completion was received.
* @completion_code: This parameter indicates the completion status information
* for the TC.
*
* Indicate if the tc completion handler was successful. SCI_SUCCESS currently
* this method always returns success.
*/
enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler(
struct scic_sds_request *this_request,
u32 completion_code)
{
enum sci_status status = SCI_SUCCESS;
u8 sat_packet_protocol =
scic_cb_request_get_sat_protocol(this_request->user_request);
switch (SCU_GET_COMPLETION_TL_STATUS(completion_code)) {
case (SCU_TASK_DONE_GOOD << SCU_COMPLETION_TL_STATUS_SHIFT):
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
if (sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_IN
|| sat_packet_protocol == SAT_PROTOCOL_PACKET_DMA_DATA_OUT
)
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
else
sci_base_state_machine_change_state(
&this_request->started_substate_machine,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
);
break;
case (SCU_TASK_DONE_UNEXP_FIS << SCU_COMPLETION_TL_STATUS_SHIFT):
if (scic_io_request_get_number_of_bytes_transferred(this_request) <
scic_cb_io_request_get_transfer_length(this_request->user_request)) {
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS_IO_DONE_EARLY
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
status = this_request->sci_status;
}
break;
case (SCU_TASK_DONE_EXCESS_DATA << SCU_COMPLETION_TL_STATUS_SHIFT):
/* In this case, there is no UF coming after. compelte the IO now. */
scic_sds_request_set_status(
this_request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
break;
default:
if (this_request->sci_status != SCI_SUCCESS) { /* The io status was set already. This means an UF for the status
* fis was received already.
*/
/*
* A device suspension event is expected, we need to have the device
* coming out of suspension, then complete the IO. */
sci_base_state_machine_change_state(
&this_request->started_substate_machine,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
);
/* change the device state to ATAPI_ERROR. */
sci_base_state_machine_change_state(
&this_request->target_device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
);
status = this_request->sci_status;
} else { /* If receiving any non-sucess TC status, no UF received yet, then an UF for
* the status fis is coming after.
*/
scic_sds_request_set_status(
this_request,
SCU_TASK_DONE_CHECK_RESPONSE,
SCI_FAILURE_IO_RESPONSE_VALID
);
sci_base_state_machine_change_state(
&this_request->started_substate_machine,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
);
}
break;
}
return status;
}
/**
* This method processes an unsolicited frame.
* @this_request: This parameter specifies the request for which the
* unsolicited frame was received.
* @frame_index: This parameter indicates the unsolicited frame index that
* should contain the response.
*
* This method returns an indication of whether the UF frame was handled
* successfully or not. SCI_SUCCESS Currently this value is always returned and
* indicates successful processing of the TC response.
*/
enum sci_status scic_sds_stp_packet_request_command_phase_common_frame_handler(
struct scic_sds_request *request,
u32 frame_index)
{
enum sci_status status;
struct sata_fis_header *frame_header;
u32 *frame_buffer;
struct scic_sds_stp_request *this_request;
this_request = (struct scic_sds_stp_request *)request;
status = scic_sds_unsolicited_frame_control_get_header(
&(this_request->parent.owning_controller->uf_control),
frame_index,
(void **)&frame_header
);
if (status == SCI_SUCCESS) {
BUG_ON(frame_header->fis_type != SATA_FIS_TYPE_REGD2H);
/*
* Get from the frame buffer the PIO Setup Data, although we don't need
* any info from this pio setup fis. */
scic_sds_unsolicited_frame_control_get_buffer(
&(this_request->parent.owning_controller->uf_control),
frame_index,
(void **)&frame_buffer
);
scic_sds_controller_copy_sata_response(
&this_request->d2h_reg_fis, (u32 *)frame_header, frame_buffer
);
/* Frame has been decoded return it to the controller */
scic_sds_controller_release_frame(
this_request->parent.owning_controller, frame_index
);
}
return status;
}
/**
* This method processes an unsolicited frame while the packet request is
* expecting TC completion. It will process the FIS and construct sense data.
* @this_request: This parameter specifies the request for which the
* unsolicited frame was received.
* @frame_index: This parameter indicates the unsolicited frame index that
* should contain the response.
*
* This method returns an indication of whether the UF frame was handled
* successfully or not. SCI_SUCCESS Currently this value is always returned and
* indicates successful processing of the TC response.
*/
enum sci_status scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler(
struct scic_sds_request *request,
u32 frame_index)
{
struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
enum sci_status status =
scic_sds_stp_packet_request_command_phase_common_frame_handler(
request, frame_index);
if (status == SCI_SUCCESS) {
/* The command has completed with error status from target device. */
status = scic_sds_stp_packet_request_process_status_fis(
request, &this_request->d2h_reg_fis);
if (status != SCI_SUCCESS) {
scic_sds_request_set_status(
&this_request->parent,
SCU_TASK_DONE_CHECK_RESPONSE,
status
);
} else
scic_sds_request_set_status(
&this_request->parent, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
}
return status;
}
/**
* This method processes an unsolicited frame while the packet request is
* expecting TC completion. It will process the FIS and construct sense data.
* @this_request: This parameter specifies the request for which the
* unsolicited frame was received.
* @frame_index: This parameter indicates the unsolicited frame index that
* should contain the response.
*
* This method returns an indication of whether the UF frame was handled
* successfully or not. SCI_SUCCESS Currently this value is always returned and
* indicates successful processing of the TC response.
*/
enum sci_status scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler(
struct scic_sds_request *request,
u32 frame_index)
{
enum sci_status status =
scic_sds_stp_packet_request_command_phase_common_frame_handler(
request, frame_index);
struct scic_sds_stp_request *this_request = (struct scic_sds_stp_request *)request;
if (status == SCI_SUCCESS) {
/* The command has completed with error status from target device. */
status = scic_sds_stp_packet_request_process_status_fis(
request, &this_request->d2h_reg_fis);
if (status != SCI_SUCCESS) {
scic_sds_request_set_status(
request,
SCU_TASK_DONE_CHECK_RESPONSE,
status
);
} else
scic_sds_request_set_status(
request, SCU_TASK_DONE_GOOD, SCI_SUCCESS
);
/*
* Always complete the NON_DATA command right away, no need to delay completion
* even an error status fis came from target device. */
sci_base_state_machine_change_state(
&request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
}
return status;
}
enum sci_status scic_sds_stp_packet_request_started_completion_delay_complete_handler(
struct sci_base_request *request)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)request;
sci_base_state_machine_change_state(
&this_request->parent.state_machine,
SCI_BASE_REQUEST_STATE_COMPLETED
);
return this_request->sci_status;
}
/* --------------------------------------------------------------------------- */
const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[] = {
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler
.tc_completion_handler = scic_sds_stp_packet_request_packet_phase_await_tc_completion_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_request_default_frame_handler
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_stp_packet_request_packet_phase_await_pio_setup_frame_handler
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler
.tc_completion_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_stp_packet_request_command_phase_await_tc_completion_frame_handler
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_request_default_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_stp_packet_request_command_phase_await_d2h_fis_frame_handler
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = {
.parent.start_handler = scic_sds_request_default_start_handler,
.parent.abort_handler = scic_sds_request_started_state_abort_handler,
.parent.complete_handler = scic_sds_stp_packet_request_started_completion_delay_complete_handler,
.parent.destruct_handler = scic_sds_request_default_destruct_handler
.tc_completion_handler = scic_sds_request_default_tc_completion_handler,
.event_handler = scic_sds_request_default_event_handler,
.frame_handler = scic_sds_request_default_frame_handler
},
};
void scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_stp_packet_request_started_substate_handler_table,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
);
scic_sds_remote_device_set_working_request(
this_request->target_device, this_request
);
}
void scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_stp_packet_request_started_substate_handler_table,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE
);
}
void scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
u8 sat_packet_protocol =
scic_cb_request_get_sat_protocol(this_request->user_request);
struct scu_task_context *task_context;
enum sci_status status;
/*
* Recycle the TC and reconstruct it for sending out data fis containing
* CDB. */
task_context = scic_sds_controller_get_task_context_buffer(
this_request->owning_controller, this_request->io_tag);
if (sat_packet_protocol == SAT_PROTOCOL_PACKET_NON_DATA)
scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
this_request, task_context);
else
scu_stp_packet_request_command_phase_construct_task_context(
this_request, task_context);
/* send the new TC out. */
status = this_request->owning_controller->state_handlers->parent.continue_io_handler(
&this_request->owning_controller->parent,
&this_request->target_device->parent,
&this_request->parent
);
if (status == SCI_SUCCESS)
SET_STATE_HANDLER(
this_request,
scic_sds_stp_packet_request_started_substate_handler_table,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE
);
}
void scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_stp_packet_request_started_substate_handler_table,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE
);
}
void scic_sds_stp_packet_request_started_completion_delay_enter(
struct sci_base_object *object)
{
struct scic_sds_request *this_request = (struct scic_sds_request *)object;
SET_STATE_HANDLER(
this_request,
scic_sds_stp_packet_request_started_substate_handler_table,
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE
);
}
/* --------------------------------------------------------------------------- */
const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[] = {
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
.enter_state = scic_sds_stp_packet_request_started_packet_phase_await_tc_completion_enter,
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE] = {
.enter_state = scic_sds_stp_packet_request_started_packet_phase_await_pio_setup_enter,
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE] = {
.enter_state = scic_sds_stp_packet_request_started_command_phase_await_tc_completion_enter,
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE] = {
.enter_state = scic_sds_stp_packet_request_started_command_phase_await_d2h_fis_enter,
},
[SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE] = {
.enter_state scic_sds_stp_packet_request_started_completion_delay_enter,
}
};
#endif /* !defined(DISABLE_ATAPI) */

View File

@ -0,0 +1,154 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_STP_PACKET_REQUEST_H_
#define _SCIC_SDS_STP_PACKET_REQUEST_H_
#include "intel_sas.h"
#include "sci_types.h"
#include "scic_sds_stp_request.h"
/**
* This file contains the structures and constants for PACKET protocol requests.
*
*
*/
/**
*
*
* This is the enumeration of the SATA PIO DATA IN started substate machine.
*/
enum _SCIC_SDS_STP_PACKET_REQUEST_STARTED_SUBSTATES {
/**
* While in this state the IO request object is waiting for the TC completion
* notification for the H2D Register FIS
*/
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
/**
* While in this state the IO request object is waiting for either a PIO Setup.
*/
SCIC_SDS_STP_PACKET_REQUEST_STARTED_PACKET_PHASE_AWAIT_PIO_SETUP_SUBSTATE,
/**
* While in this state the IO request object is waiting for TC completion for
* the Packet DMA DATA fis or Raw Frame.
*/
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_TC_COMPLETION_SUBSTATE,
/**
* The non-data IO transit to this state in this state after receiving TC
* completion. While in this state IO request object is waiting for D2H status
* frame as UF.
*/
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMMAND_PHASE_AWAIT_D2H_FIS_SUBSTATE,
/**
* The IO transit to this state in this state if the previous TC completion status
* is not success and the atapi device is suspended due to target device failed the IO.
* While in this state IO request object is waiting for device coming out of the
* suspension state then complete the IO.
*/
SCIC_SDS_STP_PACKET_REQUEST_STARTED_COMPLETION_DELAY_SUBSTATE,
};
#if !defined(DISABLE_ATAPI)
extern const struct sci_base_state scic_sds_stp_packet_request_started_substate_table[];
extern const struct scic_sds_io_request_state_handler scic_sds_stp_packet_request_started_substate_handler_table[];
#endif /* !defined(DISABLE_ATAPI) */
#if !defined(DISABLE_ATAPI)
enum sci_status scic_sds_stp_packet_request_construct(
struct scic_sds_request *this_request);
#else /* !defined(DISABLE_ATAPI) */
#define scic_sds_stp_packet_request_construct(request) SCI_FAILURE
#endif /* !defined(DISABLE_ATAPI) */
#if !defined(DISABLE_ATAPI)
void scu_stp_packet_request_command_phase_construct_task_context(
struct scic_sds_request *this_request,
struct scu_task_context *task_context);
#else /* !defined(DISABLE_ATAPI) */
#define scu_stp_packet_request_command_phase_construct_task_context(reqeust, tc)
#endif /* !defined(DISABLE_ATAPI) */
#if !defined(DISABLE_ATAPI)
void scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(
struct scic_sds_request *this_request,
struct scu_task_context *task_context);
#else /* !defined(DISABLE_ATAPI) */
#define scu_stp_packet_request_command_phase_reconstruct_raw_frame_task_context(reqeust, tc)
#endif /* !defined(DISABLE_ATAPI) */
#if !defined(DISABLE_ATAPI)
enum sci_status scic_sds_stp_packet_request_process_status_fis(
struct scic_sds_request *this_request,
struct sata_fis_reg_d2h *status_fis);
#else /* !defined(DISABLE_ATAPI) */
#define scic_sds_stp_packet_request_process_status_fis(reqeust, fis) SCI_FAILURE
#endif /* !defined(DISABLE_ATAPI) */
#if !defined(DISABLE_ATAPI)
void scic_sds_stp_packet_internal_request_sense_build_sgl(
struct scic_sds_request *this_request);
#else /* !defined(DISABLE_ATAPI) */
#define scic_sds_stp_packet_internal_request_sense_build_sgl(request)
#endif /* !defined(DISABLE_ATAPI) */
#endif /* _SCIC_SDS_STP_PACKET_REQUEST_H_ */

View File

@ -0,0 +1,116 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_SATA_PIO_REQUEST_H_
#define _SCIC_SDS_SATA_PIO_REQUEST_H_
#include "sci_base_state.h"
#include "scic_sds_request.h"
#include "scu_task_context.h"
/**
* This file contains the structures and constants for SATA PIO requests.
*
*
*/
/**
*
*
* This is the enumeration of the SATA PIO DATA IN started substate machine.
*/
enum _SCIC_SDS_STP_REQUEST_STARTED_PIO_SUBSTATES {
/**
* While in this state the IO request object is waiting for the TC completion
* notification for the H2D Register FIS
*/
SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_H2D_COMPLETION_SUBSTATE,
/**
* While in this state the IO request object is waiting for either a PIO Setup
* FIS or a D2H register FIS. The type of frame received is based on the
* result of the prior frame and line conditions.
*/
SCIC_SDS_STP_REQUEST_STARTED_PIO_AWAIT_FRAME_SUBSTATE,
/**
* While in this state the IO request object is waiting for a DATA frame from
* the device.
*/
SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_IN_AWAIT_DATA_SUBSTATE,
/**
* While in this state the IO request object is waiting to transmit the next data
* frame to the device.
*/
SCIC_SDS_STP_REQUEST_STARTED_PIO_DATA_OUT_TRANSMIT_DATA_SUBSTATE,
};
/* --------------------------------------------------------------------------- */
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_pio_substate_handler_table[];
extern const struct sci_base_state scic_sds_stp_request_started_pio_substate_table[];
/* --------------------------------------------------------------------------- */
struct scic_sds_stp_request;
struct scu_sgl_element *scic_sds_stp_request_pio_get_next_sgl(
struct scic_sds_stp_request *this_request);
#endif /* _SCIC_SDS_SATA_PIO_REQUEST_H_ */

View File

@ -0,0 +1,975 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the ready substate handlers for an STP device.
*
*
*/
#include "intel_sat.h"
#include "intel_ata.h"
#include "intel_sata.h"
#include "sci_environment.h"
#include "scic_remote_device.h"
#include "scic_user_callback.h"
#include "scic_sds_controller.h"
#include "scic_sds_port.h"
#include "scic_sds_remote_device.h"
#include "scic_sds_request.h"
#include "scu_event_codes.h"
/**
* This method will perform the STP request completion processing common to IO
* requests and task requests of all types
* @device: This parameter specifies the device for which the request is being
* completed.
* @request: This parameter specifies the request being completed.
*
* This method returns an indication as to whether the request processing
* completed successfully.
*/
static enum sci_status scic_sds_stp_remote_device_complete_request(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
struct scic_sds_request *the_request = (struct scic_sds_request *)request;
enum sci_status status;
status = scic_sds_io_request_complete(the_request);
if (status == SCI_SUCCESS) {
status = scic_sds_port_complete_io(
this_device->owning_port, this_device, the_request
);
if (status == SCI_SUCCESS) {
scic_sds_remote_device_decrement_request_count(this_device);
if (the_request->sci_status == SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED) {
/*
* This request causes hardware error, device needs to be Lun Reset.
* So here we force the state machine to IDLE state so the rest IOs
* can reach RNC state handler, these IOs will be completed by RNC with
* status of "DEVICE_RESET_REQUIRED", instead of "INVALID STATE". */
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
);
} else if (scic_sds_remote_device_get_request_count(this_device) == 0) {
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
);
}
}
}
if (status != SCI_SUCCESS)
dev_err(scirdev_to_dev(this_device),
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
"could not complete\n",
__func__,
this_device->owning_port,
this_device,
the_request,
status);
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY COMMON SUBSTATE HANDLERS
* ***************************************************************************** */
/**
* This is the READY NCQ substate handler to start task management request. In
* this routine, we suspend and resume the RNC.
* @device: The target device a task management request towards to.
* @request: The task request.
*
* enum sci_status Always return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS status to
* let controller_start_task_handler know that the controller can't post TC for
* task request yet, instead, when RNC gets resumed, a controller_continue_task
* callback will be called.
*/
static enum sci_status scic_sds_stp_remote_device_ready_substate_start_request_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
enum sci_status status;
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
struct scic_sds_request *this_request = (struct scic_sds_request *)request;
/* Will the port allow the io request to start? */
status = this_device->owning_port->state_handlers->start_io_handler(
this_device->owning_port,
this_device,
this_request
);
if (SCI_SUCCESS == status) {
status =
scic_sds_remote_node_context_start_task(this_device->rnc, this_request);
if (SCI_SUCCESS == status) {
status = this_request->state_handlers->parent.start_handler(request);
}
if (status == SCI_SUCCESS) {
/*
* / @note If the remote device state is not IDLE this will replace
* / the request that probably resulted in the task management
* / request. */
this_device->working_request = this_request;
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
);
/*
* The remote node context must cleanup the TCi to NCQ mapping table.
* The only way to do this correctly is to either write to the TLCR
* register or to invalidate and repost the RNC. In either case the
* remote node context state machine will take the correct action when
* the remote node context is suspended and later resumed. */
scic_sds_remote_node_context_suspend(
this_device->rnc, SCI_SOFTWARE_SUSPENSION, NULL, NULL);
scic_sds_remote_node_context_resume(
this_device->rnc,
(SCICS_SDS_REMOTE_NODE_CONTEXT_CALLBACK)
scic_sds_remote_device_continue_request,
this_device);
}
scic_sds_remote_device_start_request(this_device, this_request, status);
/*
* We need to let the controller start request handler know that it can't
* post TC yet. We will provide a callback function to post TC when RNC gets
* resumed. */
return SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS;
}
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY IDLE SUBSTATE HANDLERS
* ***************************************************************************** */
/**
* This method will handle the start io operation for a sata device that is in
* the command idle state. - Evalute the type of IO request to be started -
* If its an NCQ request change to NCQ substate - If its any other command
* change to the CMD substate
* @device:
* @request:
*
* If this is a softreset we may want to have a different substate. enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_start_io_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
enum sci_status status;
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
struct scic_sds_request *io_request = (struct scic_sds_request *)request;
/* Will the port allow the io request to start? */
status = this_device->owning_port->state_handlers->start_io_handler(
this_device->owning_port,
this_device,
io_request
);
if (status == SCI_SUCCESS) {
status =
scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
if (status == SCI_SUCCESS) {
status = io_request->state_handlers->parent.start_handler(request);
}
if (status == SCI_SUCCESS) {
if (
scic_cb_request_get_sat_protocol(io_request->user_request)
== SAT_PROTOCOL_FPDMA
) {
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
);
} else {
this_device->working_request = io_request;
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
);
}
}
scic_sds_remote_device_start_request(this_device, io_request, status);
}
return status;
}
/**
*
* @[in]: device The device received event.
* @[in]: event_code The event code.
*
* This method will handle the event for a sata device that is in the idle
* state. We pick up suspension events to handle specifically to this state. We
* resume the RNC right away. enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_idle_substate_event_handler(
struct scic_sds_remote_device *this_device,
u32 event_code)
{
enum sci_status status;
status = scic_sds_remote_device_general_event_handler(this_device, event_code);
if (status == SCI_SUCCESS) {
if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
|| scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
status = scic_sds_remote_node_context_resume(
this_device->rnc, NULL, NULL);
}
}
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
* ***************************************************************************** */
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
enum sci_status status;
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
struct scic_sds_request *io_request = (struct scic_sds_request *)request;
if (
scic_cb_request_get_sat_protocol(io_request->user_request)
== SAT_PROTOCOL_FPDMA
) {
status = this_device->owning_port->state_handlers->start_io_handler(
this_device->owning_port,
this_device,
io_request
);
if (status == SCI_SUCCESS) {
status = scic_sds_remote_node_context_start_io(this_device->rnc, io_request);
if (status == SCI_SUCCESS) {
status = io_request->state_handlers->parent.start_handler(request);
}
scic_sds_remote_device_start_request(this_device, io_request, status);
}
} else {
status = SCI_FAILURE_INVALID_STATE;
}
return status;
}
/**
* This method will handle events received while the STP device is in the ready
* command substate.
* @this_device: This is the device object that is receiving the event.
* @event_code: The event code to process.
*
* enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_ncq_substate_frame_handler(
struct scic_sds_remote_device *this_device,
u32 frame_index)
{
enum sci_status status;
struct sata_fis_header *frame_header;
status = scic_sds_unsolicited_frame_control_get_header(
&(scic_sds_remote_device_get_controller(this_device)->uf_control),
frame_index,
(void **)&frame_header
);
if (status == SCI_SUCCESS) {
if (
(frame_header->fis_type == SATA_FIS_TYPE_SETDEVBITS)
&& (frame_header->status & ATA_STATUS_REG_ERROR_BIT)
) {
this_device->not_ready_reason =
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED;
sci_base_state_machine_change_state(
&this_device->ready_substate_machine,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
);
} else {
status = SCI_FAILURE;
}
scic_sds_controller_release_frame(
scic_sds_remote_device_get_controller(this_device), frame_index
);
}
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY CMD SUBSTATE HANDLERS
* ***************************************************************************** */
/**
* This device is already handling a command it can not accept new commands
* until this one is complete.
* @device:
* @request:
*
* enum sci_status
*/
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
return SCI_FAILURE_INVALID_STATE;
}
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler(
struct scic_sds_remote_device *this_device,
u32 suspend_type)
{
enum sci_status status;
status = scic_sds_remote_node_context_suspend(
this_device->rnc, suspend_type, NULL, NULL
);
return status;
}
static enum sci_status scic_sds_stp_remote_device_ready_cmd_substate_frame_handler(
struct scic_sds_remote_device *this_device,
u32 frame_index)
{
enum sci_status status;
/*
* / The device doe not process any UF received from the hardware while
* / in this state. All unsolicited frames are forwarded to the io request
* / object. */
status = scic_sds_io_request_frame_handler(
this_device->working_request,
frame_index
);
return status;
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ SUBSTATE HANDLERS
* ***************************************************************************** */
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE HANDLERS
* ***************************************************************************** */
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE HANDLERS
* ***************************************************************************** */
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
return SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED;
}
/**
* This method will perform the STP request (both io or task) completion
* processing for await reset state.
* @device: This parameter specifies the device for which the request is being
* completed.
* @request: This parameter specifies the request being completed.
*
* This method returns an indication as to whether the request processing
* completed successfully.
*/
static enum sci_status scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler(
struct sci_base_remote_device *device,
struct sci_base_request *request)
{
struct scic_sds_remote_device *this_device = (struct scic_sds_remote_device *)device;
struct scic_sds_request *the_request = (struct scic_sds_request *)request;
enum sci_status status;
status = scic_sds_io_request_complete(the_request);
if (status == SCI_SUCCESS) {
status = scic_sds_port_complete_io(
this_device->owning_port, this_device, the_request
);
if (status == SCI_SUCCESS)
scic_sds_remote_device_decrement_request_count(this_device);
}
if (status != SCI_SUCCESS)
dev_err(scirdev_to_dev(this_device),
"%s: Port:0x%p Device:0x%p Request:0x%p Status:0x%x "
"could not complete\n",
__func__,
this_device->owning_port,
this_device,
the_request,
status);
return status;
}
#if !defined(DISABLE_ATAPI)
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE HANDLERS
* ***************************************************************************** */
/**
*
* @[in]: device The device received event.
* @[in]: event_code The event code.
*
* This method will handle the event for a ATAPI device that is in the ATAPI
* ERROR state. We pick up suspension events to handle specifically to this
* state. We resume the RNC right away. We then complete the outstanding IO to
* this device. enum sci_status
*/
enum sci_status scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler(
struct scic_sds_remote_device *this_device,
u32 event_code)
{
enum sci_status status;
status = scic_sds_remote_device_general_event_handler(this_device, event_code);
if (status == SCI_SUCCESS) {
if (scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX
|| scu_get_event_type(event_code) == SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX) {
status = scic_sds_remote_node_context_resume(
this_device->rnc,
this_device->working_request->state_handlers->parent.complete_handler,
(void *)this_device->working_request
);
}
}
return status;
}
#endif /* !defined(DISABLE_ATAPI) */
/* --------------------------------------------------------------------------- */
struct scic_sds_remote_device_state_handler
scic_sds_stp_remote_device_ready_substate_handler_table[
SCIC_SDS_STP_REMOTE_DEVICE_READY_MAX_SUBSTATES] =
{
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_ready_state_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_stp_remote_device_ready_idle_substate_start_io_handler,
scic_sds_remote_device_default_complete_request_handler,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_stp_remote_device_ready_substate_start_request_handler,
scic_sds_remote_device_default_complete_request_handler
},
scic_sds_remote_device_default_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_stp_remote_device_ready_idle_substate_event_handler,
scic_sds_remote_device_default_frame_handler
},
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_ready_state_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_stp_remote_device_ready_cmd_substate_start_io_handler,
scic_sds_stp_remote_device_complete_request,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_stp_remote_device_ready_substate_start_request_handler,
scic_sds_stp_remote_device_complete_request,
},
scic_sds_stp_remote_device_ready_cmd_substate_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_remote_device_general_event_handler,
scic_sds_stp_remote_device_ready_cmd_substate_frame_handler
},
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_ready_state_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_stp_remote_device_ready_ncq_substate_start_io_handler,
scic_sds_stp_remote_device_complete_request,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_stp_remote_device_ready_substate_start_request_handler,
scic_sds_stp_remote_device_complete_request
},
scic_sds_remote_device_default_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_remote_device_general_event_handler,
scic_sds_stp_remote_device_ready_ncq_substate_frame_handler
},
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_ready_state_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_remote_device_default_start_request_handler,
scic_sds_stp_remote_device_complete_request,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_stp_remote_device_ready_substate_start_request_handler,
scic_sds_stp_remote_device_complete_request
},
scic_sds_remote_device_default_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_remote_device_general_event_handler,
scic_sds_remote_device_general_frame_handler
},
#if !defined(DISABLE_ATAPI)
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_ready_state_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_remote_device_default_start_request_handler,
scic_sds_stp_remote_device_complete_request,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_stp_remote_device_ready_substate_start_request_handler,
scic_sds_stp_remote_device_complete_request
},
scic_sds_remote_device_default_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_stp_remote_device_ready_atapi_error_substate_event_handler,
scic_sds_remote_device_general_frame_handler
},
#endif
/* SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET */
{
{
scic_sds_remote_device_default_start_handler,
scic_sds_remote_device_ready_state_stop_handler,
scic_sds_remote_device_default_fail_handler,
scic_sds_remote_device_default_destruct_handler,
scic_sds_remote_device_ready_state_reset_handler,
scic_sds_remote_device_default_reset_complete_handler,
scic_sds_stp_remote_device_ready_await_reset_substate_start_io_handler,
scic_sds_stp_remote_device_ready_await_reset_substate_complete_request_handler,
scic_sds_remote_device_default_continue_request_handler,
scic_sds_stp_remote_device_ready_substate_start_request_handler,
scic_sds_stp_remote_device_complete_request
},
scic_sds_remote_device_default_suspend_handler,
scic_sds_remote_device_default_resume_handler,
scic_sds_remote_device_general_event_handler,
scic_sds_remote_device_general_frame_handler
}
};
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "sci_base_state.h"
#include "scic_remote_device.h"
#include "scic_user_callback.h"
#include "scic_sds_controller.h"
#include "scic_sds_port.h"
#include "scic_sds_remote_device.h"
#include "sci_util.h"
#include "sci_environment.h"
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY SUBSTATE PRIVATE METHODS
* ***************************************************************************** */
static void scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
void *user_cookie)
{
struct scic_sds_remote_device *this_device;
this_device = (struct scic_sds_remote_device *)user_cookie;
/*
* For NCQ operation we do not issue a
* scic_cb_remote_device_not_ready(). As a result, avoid sending
* the ready notification. */
if (this_device->ready_substate_machine.previous_state_id
!= SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ) {
scic_cb_remote_device_ready(
scic_sds_remote_device_get_controller(this_device), this_device
);
}
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY IDLE SUBSTATE
* ***************************************************************************** */
/**
*
* @device: This is the SCI base object which is cast into a
* struct scic_sds_remote_device object.
*
*/
static void scic_sds_stp_remote_device_ready_idle_substate_enter(
struct sci_base_object *device)
{
struct scic_sds_remote_device *this_device;
this_device = (struct scic_sds_remote_device *)device;
SET_STATE_HANDLER(
this_device,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE
);
this_device->working_request = NULL;
if (scic_sds_remote_node_context_is_ready(this_device->rnc)) {
/*
* Since the RNC is ready, it's alright to finish completion
* processing (e.g. signal the remote device is ready). */
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler(
this_device
);
} else {
scic_sds_remote_node_context_resume(
this_device->rnc,
scic_sds_stp_remote_device_ready_idle_substate_resume_complete_handler,
this_device
);
}
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY CMD SUBSTATE
* ***************************************************************************** */
/**
*
* @device: This is the SCI base object which is cast into a
* struct scic_sds_remote_device object.
*
*/
static void scic_sds_stp_remote_device_ready_cmd_substate_enter(
struct sci_base_object *device)
{
struct scic_sds_remote_device *this_device;
this_device = (struct scic_sds_remote_device *)device;
BUG_ON(this_device->working_request == NULL);
SET_STATE_HANDLER(
this_device,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD
);
scic_cb_remote_device_not_ready(
scic_sds_remote_device_get_controller(this_device),
this_device,
SCIC_REMOTE_DEVICE_NOT_READY_SATA_REQUEST_STARTED
);
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ SUBSTATE
* ***************************************************************************** */
/**
*
* @device: This is the SCI base object which is cast into a
* struct scic_sds_remote_device object.
*
*/
static void scic_sds_stp_remote_device_ready_ncq_substate_enter(
struct sci_base_object *device)
{
struct scic_sds_remote_device *this_device;
this_device = (struct scic_sds_remote_device *)device;
SET_STATE_HANDLER(
this_device,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ
);
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY NCQ ERROR SUBSTATE
* ***************************************************************************** */
/**
*
* @device: This is the SCI base object which is cast into a
* struct scic_sds_remote_device object.
*
*/
static void scic_sds_stp_remote_device_ready_ncq_error_substate_enter(
struct sci_base_object *device)
{
struct scic_sds_remote_device *this_device;
this_device = (struct scic_sds_remote_device *)device;
SET_STATE_HANDLER(
this_device,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR
);
if (this_device->not_ready_reason ==
SCIC_REMOTE_DEVICE_NOT_READY_SATA_SDB_ERROR_FIS_RECEIVED) {
scic_cb_remote_device_not_ready(
scic_sds_remote_device_get_controller(this_device),
this_device,
this_device->not_ready_reason
);
}
}
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY AWAIT RESET SUBSTATE
* ***************************************************************************** */
/**
* The enter routine to READY AWAIT RESET substate.
* @device: This is the SCI base object which is cast into a
* struct scic_sds_remote_device object.
*
*/
static void scic_sds_stp_remote_device_ready_await_reset_substate_enter(
struct sci_base_object *device)
{
struct scic_sds_remote_device *this_device;
this_device = (struct scic_sds_remote_device *)device;
SET_STATE_HANDLER(
this_device,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET
);
}
#if !defined(DISABLE_ATAPI)
/*
* *****************************************************************************
* * STP REMOTE DEVICE READY ATAPI ERROR SUBSTATE
* ***************************************************************************** */
/**
* The enter routine to READY ATAPI ERROR substate.
* @device: This is the SCI base object which is cast into a
* struct scic_sds_remote_device object.
*
*/
void scic_sds_stp_remote_device_ready_atapi_error_substate_enter(
struct sci_base_object *device)
{
struct scic_sds_remote_device *this_device;
this_device = (struct scic_sds_remote_device *)device;
SET_STATE_HANDLER(
this_device,
scic_sds_stp_remote_device_ready_substate_handler_table,
SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR
);
}
#endif /* !defined(DISABLE_ATAPI) */
/* --------------------------------------------------------------------------- */
const struct sci_base_state scic_sds_stp_remote_device_ready_substate_table[] = {
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_IDLE] = {
.enter_state = scic_sds_stp_remote_device_ready_idle_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_CMD] = {
.enter_state = scic_sds_stp_remote_device_ready_cmd_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ] = {
.enter_state = scic_sds_stp_remote_device_ready_ncq_substate_enter,
},
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_NCQ_ERROR] = {
.enter_state = scic_sds_stp_remote_device_ready_ncq_error_substate_enter,
},
#if !defined(DISABLE_ATAPI)
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_ATAPI_ERROR] = {
.enter_state = scic_sds_stp_remote_device_ready_atapi_error_substate_enter,
},
#endif
[SCIC_SDS_STP_REMOTE_DEVICE_READY_SUBSTATE_AWAIT_RESET] = {
.enter_state = scic_sds_stp_remote_device_ready_await_reset_substate_enter,
},
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,221 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_SDS_STP_REQUEST_T_
#define _SCIC_SDS_STP_REQUEST_T_
#include "intel_sata.h"
#include "sci_types.h"
#include "scic_sds_request.h"
/**
* This structure represents the additional information that is required to
* handle SATA PIO requests.
*
*
*/
struct scic_sds_stp_request {
struct scic_sds_request parent;
struct sata_fis_reg_d2h d2h_reg_fis;
union {
u32 ncq;
u32 udma;
struct {
/**
* Total transfer for the entire PIO request recorded at request constuction
* time.
*
* @todo Should we just decrement this value for each byte of data transitted
* or received to elemenate the current_transfer_bytes field?
*/
u32 total_transfer_bytes;
/**
* Total number of bytes received/transmitted in data frames since the start
* of the IO request. At the end of the IO request this should equal the
* total_transfer_bytes.
*/
u32 current_transfer_bytes;
/**
* The number of bytes requested in the in the PIO setup.
*/
u32 pio_transfer_bytes;
/**
* PIO Setup ending status value to tell us if we need to wait for another FIS
* or if the transfer is complete. On the receipt of a D2H FIS this will be
* the status field of that FIS.
*/
u8 ending_status;
/**
* On receipt of a D2H FIS this will be the ending error field if the
* ending_status has the SATA_STATUS_ERR bit set.
*/
u8 ending_error;
/**
* Protocol Type. This is filled in by core during IO Request construction type.
*/
u8 sat_protocol;
struct {
struct scu_sgl_element_pair *sgl_pair;
u8 sgl_set;
u32 sgl_offset;
} request_current;
} pio;
struct {
/**
* The number of bytes requested in the PIO setup before CDB data frame.
*/
u32 device_preferred_cdb_length;
} packet;
} type;
};
/**
* enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES - This enumeration depicts
* the various sub-states associated with a SATA/STP UDMA protocol operation.
*
*
*/
enum SCIC_SDS_STP_REQUEST_STARTED_UDMA_SUBSTATES {
SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_TC_COMPLETION_SUBSTATE,
SCIC_SDS_STP_REQUEST_STARTED_UDMA_AWAIT_D2H_REG_FIS_SUBSTATE,
};
/**
* enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES - This enumeration
* depicts the various sub-states associated with a SATA/STP non-data
* protocol operation.
*
*
*/
enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES {
SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_H2D_COMPLETION_SUBSTATE,
SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_AWAIT_D2H_SUBSTATE,
};
/**
* enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES - THis enumeration
* depicts the various sub-states associated with a SATA/STP soft reset
* operation.
*
*
*/
enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES {
SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_ASSERTED_COMPLETION_SUBSTATE,
SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_H2D_DIAGNOSTIC_COMPLETION_SUBSTATE,
SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_AWAIT_D2H_RESPONSE_FRAME_SUBSTATE,
};
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_udma_substate_handler_table[];
extern const struct sci_base_state scic_sds_stp_request_started_udma_substate_table[];
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_non_data_substate_handler_table[];
extern const struct sci_base_state scic_sds_stp_request_started_non_data_substate_table[];
extern const struct scic_sds_io_request_state_handler scic_sds_stp_request_started_soft_reset_substate_handler_table[];
extern const struct sci_base_state scic_sds_stp_request_started_soft_reset_substate_table[];
/* --------------------------------------------------------------------------- */
u32 scic_sds_stp_request_get_object_size(void);
void scic_sds_stp_non_ncq_request_construct(
struct scic_sds_request *this_request);
enum sci_status scic_sds_stp_pio_request_construct(
struct scic_sds_request *scic_io_request,
u8 sat_protocol,
bool copy_rx_frame);
enum sci_status scic_sds_stp_pio_request_construct_pass_through(
struct scic_sds_request *scic_io_request,
struct scic_stp_passthru_request_callbacks *passthru_cb);
enum sci_status scic_sds_stp_udma_request_construct(
struct scic_sds_request *this_request,
u32 transfer_length,
SCI_IO_REQUEST_DATA_DIRECTION data_direction);
enum sci_status scic_sds_stp_non_data_request_construct(
struct scic_sds_request *this_request);
enum sci_status scic_sds_stp_soft_reset_request_construct(
struct scic_sds_request *this_request);
enum sci_status scic_sds_stp_ncq_request_construct(
struct scic_sds_request *this_request,
u32 transfer_length,
SCI_IO_REQUEST_DATA_DIRECTION data_direction);
void scu_stp_raw_request_construct_task_context(
struct scic_sds_stp_request *this_request,
struct scu_task_context *task_context);
#endif /* _SCIC_SDS_STP_REQUEST_T_ */

View File

@ -0,0 +1,379 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the implementation of the
* struct scic_sds_unsolicited_frame_control object and it's public, protected, and
* private methods.
*
*
*/
#include "scic_sds_unsolicited_frame_control.h"
#include "scu_registers.h"
#include "scic_sds_controller.h"
#include "scic_user_callback.h"
#include "sci_util.h"
#include "sci_environment.h"
/**
* The UF buffer address table size must be programmed to a power of 2. Find
* the first power of 2 that is equal to or greater then the number of
* unsolicited frame buffers to be utilized.
* @uf_control: This parameter specifies the UF control object for which to
* update the address table count.
*
*/
void scic_sds_unsolicited_frame_control_set_address_table_count(
struct scic_sds_unsolicited_frame_control *uf_control)
{
uf_control->address_table.count = SCU_MIN_UF_TABLE_ENTRIES;
while (
(uf_control->address_table.count < uf_control->buffers.count)
&& (uf_control->address_table.count < SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES)
) {
uf_control->address_table.count <<= 1;
}
}
/**
* This method will program the unsolicited frames (UFs) into the UF address
* table and construct the UF frame structure being modeled in the core. It
* will handle the case where some of the UFs are not being used and thus
* should have entries programmed to zero in the address table.
* @uf_control: This parameter specifies the unsolicted frame control object
* for which to construct the unsolicited frames objects.
* @uf_buffer_phys_address: This parameter specifies the physical address for
* the first unsolicited frame buffer.
* @uf_buffer_virt_address: This parameter specifies the virtual address for
* the first unsolicited frame buffer.
* @unused_uf_header_entries: This parameter specifies the number of unused UF
* headers. This value can be non-zero when there are a non-power of 2
* number of unsolicited frames being supported.
* @used_uf_header_entries: This parameter specifies the number of actually
* utilized UF headers.
*
*/
static void scic_sds_unsolicited_frame_control_construct_frames(
struct scic_sds_unsolicited_frame_control *uf_control,
dma_addr_t uf_buffer_phys_address,
unsigned long uf_buffer_virt_address,
u32 unused_uf_header_entries,
u32 used_uf_header_entries)
{
u32 index;
struct scic_sds_unsolicited_frame *uf;
/*
* Program the unused buffers into the UF address table and the
* controller's array of UFs. */
for (index = 0; index < unused_uf_header_entries; index++) {
uf = &uf_control->buffers.array[index];
sci_cb_make_physical_address(
uf_control->address_table.array[index], 0, 0
);
uf->buffer = NULL;
uf->header = &uf_control->headers.array[index];
uf->state = UNSOLICITED_FRAME_EMPTY;
}
/*
* Program the actual used UF buffers into the UF address table and
* the controller's array of UFs. */
for (index = unused_uf_header_entries;
index < unused_uf_header_entries + used_uf_header_entries;
index++) {
uf = &uf_control->buffers.array[index];
uf_control->address_table.array[index] = uf_buffer_phys_address;
uf->buffer = (void *)uf_buffer_virt_address;
uf->header = &uf_control->headers.array[index];
uf->state = UNSOLICITED_FRAME_EMPTY;
/*
* Increment the address of the physical and virtual memory pointers
* Everything is aligned on 1k boundary with an increment of 1k */
uf_buffer_virt_address += SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
sci_physical_address_add(
uf_buffer_phys_address, SCU_UNSOLICITED_FRAME_BUFFER_SIZE
);
}
}
/**
* This method constructs the various members of the unsolicted frame control
* object (buffers, headers, address, table, etc).
* @uf_control: This parameter specifies the unsolicited frame control object
* to construct.
* @mde: This parameter specifies the memory descriptor from which to derive
* all of the address information needed to get the unsolicited frame
* functionality working.
* @controller: This parameter specifies the controller object associated with
* the uf_control being constructed.
*
*/
void scic_sds_unsolicited_frame_control_construct(
struct scic_sds_unsolicited_frame_control *uf_control,
struct sci_physical_memory_descriptor *mde,
struct scic_sds_controller *controller)
{
u32 unused_uf_header_entries;
u32 used_uf_header_entries;
u32 used_uf_buffer_bytes;
u32 unused_uf_header_bytes;
u32 used_uf_header_bytes;
dma_addr_t uf_buffer_phys_address;
/*
* Prepare all of the memory sizes for the UF headers, UF address
* table, and UF buffers themselves. */
used_uf_buffer_bytes = uf_control->buffers.count
* SCU_UNSOLICITED_FRAME_BUFFER_SIZE;
unused_uf_header_entries = uf_control->address_table.count
- uf_control->buffers.count;
used_uf_header_entries = uf_control->buffers.count;
unused_uf_header_bytes = unused_uf_header_entries
* sizeof(struct scu_unsolicited_frame_header);
used_uf_header_bytes = used_uf_header_entries
* sizeof(struct scu_unsolicited_frame_header);
/*
* The Unsolicited Frame buffers are set at the start of the UF
* memory descriptor entry. The headers and address table will be
* placed after the buffers. */
uf_buffer_phys_address = mde->physical_address;
/*
* Program the location of the UF header table into the SCU.
* Notes:
* - The address must align on a 64-byte boundary. Guaranteed to be
* on 64-byte boundary already 1KB boundary for unsolicited frames.
* - Program unused header entries to overlap with the last
* unsolicited frame. The silicon will never DMA to these unused
* headers, since we program the UF address table pointers to
* NULL. */
uf_control->headers.physical_address = uf_buffer_phys_address;
sci_physical_address_add(
uf_control->headers.physical_address, used_uf_buffer_bytes);
sci_physical_address_subtract(
uf_control->headers.physical_address, unused_uf_header_bytes);
uf_control->headers.array
= (struct scu_unsolicited_frame_header *)
scic_cb_get_virtual_address(
controller, uf_control->headers.physical_address
);
/*
* Program the location of the UF address table into the SCU.
* Notes:
* - The address must align on a 64-bit boundary. Guaranteed to be on 64
* byte boundary already due to above programming headers being on a
* 64-bit boundary and headers are on a 64-bytes in size. */
uf_control->address_table.physical_address = uf_buffer_phys_address;
sci_physical_address_add(
uf_control->address_table.physical_address, used_uf_buffer_bytes);
sci_physical_address_add(
uf_control->address_table.physical_address, used_uf_header_bytes);
uf_control->address_table.array
= (dma_addr_t *)
scic_cb_get_virtual_address(
controller, uf_control->address_table.physical_address
);
uf_control->get = 0;
/*
* UF buffer requirements are:
* - The last entry in the UF queue is not NULL.
* - There is a power of 2 number of entries (NULL or not-NULL)
* programmed into the queue.
* - Aligned on a 1KB boundary. */
/*
* If the user provided less then the maximum amount of memory,
* then be sure that we programm the first entries in the UF
* address table to NULL. */
scic_sds_unsolicited_frame_control_construct_frames(
uf_control,
uf_buffer_phys_address,
(unsigned long)mde->virtual_address,
unused_uf_header_entries,
used_uf_header_entries
);
}
/**
* This method returns the frame header for the specified frame index.
* @uf_control:
* @frame_index:
* @frame_header:
*
* enum sci_status
*/
enum sci_status scic_sds_unsolicited_frame_control_get_header(
struct scic_sds_unsolicited_frame_control *uf_control,
u32 frame_index,
void **frame_header)
{
if (frame_index < uf_control->address_table.count) {
/*
* Skip the first word in the frame since this is a controll word used
* by the hardware. */
*frame_header = &uf_control->buffers.array[frame_index].header->data;
return SCI_SUCCESS;
}
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
}
/**
* This method returns the frame buffer for the specified frame index.
* @uf_control:
* @frame_index:
* @frame_buffer:
*
* enum sci_status
*/
enum sci_status scic_sds_unsolicited_frame_control_get_buffer(
struct scic_sds_unsolicited_frame_control *uf_control,
u32 frame_index,
void **frame_buffer)
{
if (frame_index < uf_control->address_table.count) {
*frame_buffer = uf_control->buffers.array[frame_index].buffer;
return SCI_SUCCESS;
}
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
}
/**
* This method releases the frame once this is done the frame is available for
* re-use by the hardware. The data contained in the frame header and frame
* buffer is no longer valid.
* @uf_control: This parameter specifies the UF control object
* @frame_index: This parameter specifies the frame index to attempt to release.
*
* This method returns an indication to the caller as to whether the
* unsolicited frame get pointer should be updated. true This value indicates
* the unsolicited frame get pointer should be updated (i.e. write
* SCU_UFQGP_WRITE). false This value indicates the get pointer should not be
* updated.
*/
bool scic_sds_unsolicited_frame_control_release_frame(
struct scic_sds_unsolicited_frame_control *uf_control,
u32 frame_index)
{
u32 frame_get;
u32 frame_cycle;
frame_get = uf_control->get & (uf_control->address_table.count - 1);
frame_cycle = uf_control->get & uf_control->address_table.count;
/*
* In the event there are NULL entries in the UF table, we need to
* advance the get pointer in order to find out if this frame should
* be released (i.e. update the get pointer). */
while (((lower_32_bits(uf_control->address_table.array[frame_get])
== 0) &&
(upper_32_bits(uf_control->address_table.array[frame_get])
== 0)) &&
(frame_get < uf_control->address_table.count))
frame_get++;
/*
* The table has a NULL entry as it's last element. This is
* illegal. */
BUG_ON(frame_get >= uf_control->address_table.count);
if (frame_index < uf_control->address_table.count) {
uf_control->buffers.array[frame_index].state = UNSOLICITED_FRAME_RELEASED;
/*
* The frame index is equal to the current get pointer so we
* can now free up all of the frame entries that */
if (frame_get == frame_index) {
while (
uf_control->buffers.array[frame_get].state
== UNSOLICITED_FRAME_RELEASED
) {
uf_control->buffers.array[frame_get].state = UNSOLICITED_FRAME_EMPTY;
INCREMENT_QUEUE_GET(
frame_get,
frame_cycle,
uf_control->address_table.count - 1,
uf_control->address_table.count
);
}
uf_control->get =
(SCU_UFQGP_GEN_BIT(ENABLE_BIT) | frame_cycle | frame_get);
return true;
} else {
/*
* Frames remain in use until we advance the get pointer
* so there is nothing we can do here */
}
}
return false;
}

View File

@ -0,0 +1,286 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains all of the unsolicited frame related management for the
* address table, the headers, and actual payload buffers.
*
*
*/
#ifndef _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
#define _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_
#include "scu_unsolicited_frame.h"
#include "sci_memory_descriptor_list.h"
#include "scu_constants.h"
#include "sci_status.h"
/**
* enum UNSOLICITED_FRAME_STATE -
*
* This enumeration represents the current unsolicited frame state. The
* controller object can not updtate the hardware unsolicited frame put pointer
* unless it has already processed the priror unsolicited frames.
*/
enum UNSOLICITED_FRAME_STATE {
/**
* This state is when the frame is empty and not in use. It is
* different from the released state in that the hardware could DMA
* data to this frame buffer.
*/
UNSOLICITED_FRAME_EMPTY,
/**
* This state is set when the frame buffer is in use by by some
* object in the system.
*/
UNSOLICITED_FRAME_IN_USE,
/**
* This state is set when the frame is returned to the free pool
* but one or more frames prior to this one are still in use.
* Once all of the frame before this one are freed it will go to
* the empty state.
*/
UNSOLICITED_FRAME_RELEASED,
UNSOLICITED_FRAME_MAX_STATES
};
/**
* struct scic_sds_unsolicited_frame -
*
* This is the unsolicited frame data structure it acts as the container for
* the current frame state, frame header and frame buffer.
*/
struct scic_sds_unsolicited_frame {
/**
* This field contains the current frame state
*/
enum UNSOLICITED_FRAME_STATE state;
/**
* This field points to the frame header data.
*/
struct scu_unsolicited_frame_header *header;
/**
* This field points to the frame buffer data.
*/
void *buffer;
};
/**
* struct scic_sds_uf_header_array -
*
* This structure contains all of the unsolicited frame header information.
*/
struct scic_sds_uf_header_array {
/**
* This field is represents a virtual pointer to the start
* address of the UF address table. The table contains
* 64-bit pointers as required by the hardware.
*/
struct scu_unsolicited_frame_header *array;
/**
* This field specifies the physical address location for the UF
* buffer array.
*/
dma_addr_t physical_address;
};
/*
* Determine the size of the unsolicited frame array including
* unused buffers. */
#if SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES
#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MIN_UF_TABLE_ENTRIES
#else
#define SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE SCU_MAX_UNSOLICITED_FRAMES
#endif /* SCU_UNSOLICITED_FRAME_COUNT <= SCU_MIN_UF_TABLE_ENTRIES */
/**
* struct scic_sds_uf_buffer_array -
*
* This structure contains all of the unsolicited frame buffer (actual payload)
* information.
*/
struct scic_sds_uf_buffer_array {
/**
* This field is the minimum number of unsolicited frames supported by the
* hardware and the number of unsolicited frames requested by the software.
*/
u32 count;
/**
* This field is the SCIC_UNSOLICITED_FRAME data its used to manage
* the data for the unsolicited frame requests. It also represents
* the virtual address location that corresponds to the
* physical_address field.
*/
struct scic_sds_unsolicited_frame array[SCU_UNSOLICITED_FRAME_CONTROL_ARRAY_SIZE];
/**
* This field specifies the physical address location for the UF
* buffer array.
*/
dma_addr_t physical_address;
};
/**
* struct scic_sds_uf_address_table_array -
*
* This object maintains all of the unsolicited frame address table specific
* data. The address table is a collection of 64-bit pointers that point to
* 1KB buffers into which the silicon will DMA unsolicited frames.
*/
struct scic_sds_uf_address_table_array {
/**
* This field specifies the actual programmed size of the
* unsolicited frame buffer address table. The size of the table
* can be larger than the actual number of UF buffers, but it must
* be a power of 2 and the last entry in the table is not allowed
* to be NULL.
*/
u32 count;
/**
* This field represents a virtual pointer that refers to the
* starting address of the UF address table.
* 64-bit pointers are required by the hardware.
*/
dma_addr_t *array;
/**
* This field specifies the physical address location for the UF
* address table.
*/
dma_addr_t physical_address;
};
/**
* struct scic_sds_unsolicited_frame_control -
*
* This object contains all of the data necessary to handle unsolicited frames.
*/
struct scic_sds_unsolicited_frame_control {
/**
* This field is the software copy of the unsolicited frame queue
* get pointer. The controller object writes this value to the
* hardware to let the hardware put more unsolicited frame entries.
*/
u32 get;
/**
* This field contains all of the unsolicited frame header
* specific fields.
*/
struct scic_sds_uf_header_array headers;
/**
* This field contains all of the unsolicited frame buffer
* specific fields.
*/
struct scic_sds_uf_buffer_array buffers;
/**
* This field contains all of the unsolicited frame address table
* specific fields.
*/
struct scic_sds_uf_address_table_array address_table;
};
void scic_sds_unsolicited_frame_control_set_address_table_count(
struct scic_sds_unsolicited_frame_control *uf_control);
struct scic_sds_controller;
void scic_sds_unsolicited_frame_control_construct(
struct scic_sds_unsolicited_frame_control *uf_control,
struct sci_physical_memory_descriptor *mde,
struct scic_sds_controller *this_controller);
enum sci_status scic_sds_unsolicited_frame_control_get_header(
struct scic_sds_unsolicited_frame_control *uf_control,
u32 frame_index,
void **frame_header);
enum sci_status scic_sds_unsolicited_frame_control_get_buffer(
struct scic_sds_unsolicited_frame_control *uf_control,
u32 frame_index,
void **frame_buffer);
bool scic_sds_unsolicited_frame_control_release_frame(
struct scic_sds_unsolicited_frame_control *uf_control,
u32 frame_index);
/**
* scic_sds_unsolicited_frame_control_get_mde_size() -
*
* This macro simply calculates the size of the memory descriptor entry that
* relates to unsolicited frames and the surrounding silicon memory required to
* utilize it.
*/
#define scic_sds_unsolicited_frame_control_get_mde_size(uf_control) \
(((uf_control).buffers.count * SCU_UNSOLICITED_FRAME_BUFFER_SIZE) \
+ ((uf_control).address_table.count * sizeof(dma_addr_t)) \
+ ((uf_control).buffers.count * sizeof(struct scu_unsolicited_frame_header)))
#endif /* _SCIC_SDS_UNSOLICITED_FRAME_CONTROL_H_ */

View File

@ -0,0 +1,148 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_TASK_REQUEST_H_
#define _SCIC_TASK_REQUEST_H_
/**
* This file contains the structures and interface methods that can be
* referenced and used by the SCI user for to utilize task management
* requests.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
struct scic_sds_request;
struct scic_sds_remote_device;
struct scic_sds_controller;
/**
* scic_task_request_construct() - This method is called by the SCI user to
* construct all SCI Core task management requests, regardless of protocol.
* Memory initialization and functionality common to all task request types
* is performed in this method.
* @scic_controller: the handle to the core controller object for which to
* build the task managmement request.
* @scic_remote_device: the handle to the core remote device object for which
* to build the task management request. passed, then a copy of the request
* is built internally. The request will be copied into the actual
* controller request memory when the task is allocated internally during
* the scic_controller_start_task() method.
* @io_tag: This parameter specifies the IO tag to be associated with this
* request. If SCI_CONTROLLER_INVALID_IO_TAG is passed, then a copy of the
* request is built internally. The request will be copied into the actual
* controller request memory when the IO tag is allocated internally during
* the scic_controller_start_io() method.
* @user_task_request_object: This parameter specifies the user task request to
* be utilized during construction. This task pointer will become the
* associated object for the core task request object.
* @scic_task_request_memory: This parameter specifies the memory location to
* be utilized when building the core request.
* @new_scic_task_request_handle: This parameter specifies a pointer to the
* handle the core will expect in further interactions with the core task
* request object.
*
* The SCI core implementation will create an association between the user task
* request object and the core task request object. Indicate if the controller
* successfully built the task request. SCI_SUCCESS This value is returned if
* the task request was successfully built.
*/
enum sci_status scic_task_request_construct(
struct scic_sds_controller *scic_controller,
struct scic_sds_remote_device *scic_remote_device,
u16 io_tag,
void *user_task_request_object,
void *scic_task_request_memory,
struct scic_sds_request **new_scic_task_request_handle);
/**
* scic_task_request_construct_ssp() - This method is called by the SCI user to
* construct all SCI Core SSP task management requests. Memory
* initialization and functionality common to all task request types is
* performed in this method.
* @scic_task_request: This parameter specifies the handle to the core task
* request object for which to construct a SATA specific task management
* request.
*
* Indicate if the controller successfully built the task request. SCI_SUCCESS
* This value is returned if the task request was successfully built.
*/
enum sci_status scic_task_request_construct_ssp(
struct scic_sds_request *scic_task_request);
/**
* scic_task_request_construct_sata() - This method is called by the SCI user
* to construct all SCI Core SATA task management requests. Memory
* initialization and functionality common to all task request types is
* performed in this method.
* @scic_task_request_handle: This parameter specifies the handle to the core
* task request object for which to construct a SATA specific task
* management request.
*
* Indicate if the controller successfully built the task request. SCI_SUCCESS
* This value is returned if the task request was successfully built.
*/
enum sci_status scic_task_request_construct_sata(
struct scic_sds_request *scic_task_request_handle);
#endif /* _SCIC_TASK_REQUEST_H_ */

View File

@ -0,0 +1,740 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCIC_USER_CALLBACK_H_
#define _SCIC_USER_CALLBACK_H_
/**
* This file contains all of the interface methods/macros that must be
* implemented by an SCI Core user.
*
*
*/
#include "sci_types.h"
#include "sci_status.h"
struct scic_sds_request;
struct scic_sds_phy;
struct scic_sds_port;
struct scic_sds_remote_device;
struct scic_sds_controller;
/**
* scic_cb_timer_create() - This callback method asks the user to create a
* timer and provide a handle for this timer for use in further timer
* interactions.
* @controller: This parameter specifies the controller with which this timer
* is to be associated.
* @timer_callback: This parameter specifies the callback method to be invoked
* whenever the timer expires.
* @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.
*
* 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()). This method returns a handle to a
* timer object created by the user. The handle will be utilized for all
* further interactions relating to this timer.
*/
void *scic_cb_timer_create(
struct scic_sds_controller *controller,
void (*timer_callback)(void *),
void *cookie);
/**
* scic_cb_timer_start() - This callback method asks the user to start the
* supplied timer.
* @controller: This parameter specifies the controller with which this timer
* is to associated.
* @timer: This parameter specifies the timer to be started.
* @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.
*
* All timers in the system started by the SCI Core are one shot timers.
* Therefore, the SCI user should make sure that it removes the timer from it's
* list when a timer actually fires. Additionally, SCI Core user's should be
* able to handle calls from the SCI Core to stop a timer that may already be
* stopped. none
*/
void scic_cb_timer_start(
struct scic_sds_controller *controller,
void *timer,
u32 milliseconds);
/**
* scic_cb_timer_stop() - This callback method asks the user to stop the
* supplied timer.
* @controller: This parameter specifies the controller with which this timer
* is to associated.
* @timer: This parameter specifies the timer to be stopped.
*
*/
void scic_cb_timer_stop(
struct scic_sds_controller *controller,
void *timer);
/**
* scic_cb_stall_execution() - 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.
* @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.
*
* none.
*/
void scic_cb_stall_execution(
u32 microseconds);
/**
* scic_cb_controller_start_complete() - This user callback will inform the
* user that the controller has finished the start process.
* @controller: This parameter specifies the controller that was started.
* @completion_status: This parameter specifies the results of the start
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_controller_start_complete(
struct scic_sds_controller *controller,
enum sci_status completion_status);
/**
* scic_cb_controller_stop_complete() - This user callback will inform the user
* that the controller has finished the stop process.
* @controller: This parameter specifies the controller that was stopped.
* @completion_status: This parameter specifies the results of the stop
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_controller_stop_complete(
struct scic_sds_controller *controller,
enum sci_status completion_status);
/**
* scic_cb_io_request_complete() - This user callback will inform the user that
* an IO request has completed.
* @controller: This parameter specifies the controller on which the IO is
* completing.
* @remote_device: This parameter specifies the remote device on which this IO
* request is completing.
* @io_request: This parameter specifies the IO request that has completed.
* @completion_status: This parameter specifies the results of the IO request
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_io_request_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *io_request,
enum sci_io_status completion_status);
/**
* scic_cb_task_request_complete() - This user callback will inform the user
* that a task management request completed.
* @controller: This parameter specifies the controller on which the task
* management request is completing.
* @remote_device: This parameter specifies the remote device on which this
* task management request is completing.
* @task_request: This parameter specifies the task management request that has
* completed.
* @completion_status: This parameter specifies the results of the IO request
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_task_request_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *task_request,
enum sci_task_status completion_status);
#ifndef SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED
/**
* scic_cb_io_request_get_physical_address() - This callback method asks the
* user to provide the physical address for the supplied virtual address
* when building an io request object.
* @controller: This parameter is the core controller object handle.
* @io_request: This parameter is the io request object handle for which the
* physical address is being requested.
* @virtual_address: This paramter is the virtual address which is to be
* returned as a physical address.
* @physical_address: The physical address for the supplied virtual address.
*
* None.
*/
void scic_cb_io_request_get_physical_address(
struct scic_sds_controller *controller,
struct scic_sds_request *io_request,
void *virtual_address,
dma_addr_t *physical_address);
#endif /* SCI_GET_PHYSICAL_ADDRESS_OPTIMIZATION_ENABLED */
/**
* scic_cb_io_request_get_transfer_length() - This callback method asks the
* user to provide the number of bytes to be transfered as part of this
* request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the number of payload data bytes to be transfered for
* this IO request.
*/
u32 scic_cb_io_request_get_transfer_length(
void *scic_user_io_request);
/**
* scic_cb_io_request_get_data_direction() - This callback method asks the user
* to provide the data direction for this request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the value of SCI_IO_REQUEST_DATA_OUT or
* SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
*/
SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
void *scic_user_io_request);
#ifndef SCI_SGL_OPTIMIZATION_ENABLED
/**
* scic_cb_io_request_get_next_sge() - 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.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
* @current_sge_address: This parameter specifies the address for the current
* SGE (i.e. the one that has just processed).
* @next_sge: An address specifying the location for the next scatter gather
* element to be processed.
*
* None
*/
void scic_cb_io_request_get_next_sge(
void *scic_user_io_request,
void *current_sge_address,
void **next_sge);
#endif /* SCI_SGL_OPTIMIZATION_ENABLED */
/**
* scic_cb_sge_get_address_field() - This callback method asks the user to
* provide the contents of the "address" field in the Scatter-Gather Element.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
* @sge_address: This parameter specifies the address for the SGE from which to
* retrieve the address field.
*
* A physical address specifying the contents of the SGE's address field.
*/
dma_addr_t scic_cb_sge_get_address_field(
void *scic_user_io_request,
void *sge_address);
/**
* scic_cb_sge_get_length_field() - This callback method asks the user to
* provide the contents of the "length" field in the Scatter-Gather Element.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
* @sge_address: This parameter specifies the address for the SGE from which to
* retrieve the address field.
*
* This method returns the length field specified inside the SGE referenced by
* the sge_address parameter.
*/
u32 scic_cb_sge_get_length_field(
void *scic_user_io_request,
void *sge_address);
/**
* scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the
* user to provide the address for the command descriptor block (CDB)
* associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the virtual address of the CDB.
*/
void *scic_cb_ssp_io_request_get_cdb_address(
void *scic_user_io_request);
/**
* scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user
* to provide the length of the command descriptor block (CDB) associated
* with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the length of the CDB.
*/
u32 scic_cb_ssp_io_request_get_cdb_length(
void *scic_user_io_request);
/**
* scic_cb_ssp_io_request_get_lun() - This callback method asks the user to
* provide the Logical Unit (LUN) associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* 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.
* This method returns the LUN associated with this request. This should be u64?
*/
u32 scic_cb_ssp_io_request_get_lun(
void *scic_user_io_request);
/**
* scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the
* user to provide the task attribute associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* 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.
* This method returns the task attribute associated with this IO request.
*/
u32 scic_cb_ssp_io_request_get_task_attribute(
void *scic_user_io_request);
/**
* scic_cb_ssp_io_request_get_command_priority() - This callback method asks
* the user to provide the command priority associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* 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.
* This method returns the command priority associated with this IO request.
*/
u32 scic_cb_ssp_io_request_get_command_priority(
void *scic_user_io_request);
/**
* scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user
* if the received RX frame data is to be copied to the SGL or should be
* stored by the SCI core to be retrieved later with the
* scic_io_request_get_rx_frame().
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns true if the SCI core should copy the received frame data
* to the SGL location or false if the SCI user wants to retrieve the frame
* data at a later time.
*/
bool scic_cb_io_request_do_copy_rx_frames(
void *scic_user_io_request);
/**
* scic_cb_request_get_sat_protocol() - This callback method asks the user to
* return the SAT protocol definition for this IO request. This method is
* only called by the SCI core if the request type constructed is SATA.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns one of the sat.h defined protocols for the given io
* request.
*/
u8 scic_cb_request_get_sat_protocol(
void *scic_user_io_request);
/**
* scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to
* be utilized for this task management request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* 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. This
* method returns the LUN associated with this request. This should be u64?
*/
u32 scic_cb_ssp_task_request_get_lun(
void *scic_user_task_request);
/**
* scic_cb_ssp_task_request_get_function() - This method returns the task
* management function to be utilized for this task request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* 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. This
* method returns an unsigned byte representing the task management function to
* be performed.
*/
u8 scic_cb_ssp_task_request_get_function(
void *scic_user_task_request);
/**
* scic_cb_ssp_task_request_get_io_tag_to_manage() - 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.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns an unsigned 16-bit word depicting the IO tag to be
* managed.
*/
u16 scic_cb_ssp_task_request_get_io_tag_to_manage(
void *scic_user_task_request);
/**
* scic_cb_ssp_task_request_get_response_data_address() - This callback method
* asks the user to provide the virtual address of the response data buffer
* for the supplied IO request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the virtual address for the response data buffer
* associated with this IO request.
*/
void *scic_cb_ssp_task_request_get_response_data_address(
void *scic_user_task_request);
/**
* scic_cb_ssp_task_request_get_response_data_length() - This callback method
* asks the user to provide the length of the response data buffer for the
* supplied IO request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the length of the response buffer data associated with
* this IO request.
*/
u32 scic_cb_ssp_task_request_get_response_data_length(
void *scic_user_task_request);
/**
* scic_cb_pci_get_bar() - In this method the user must return the base address
* register (BAR) value for the supplied base address register number.
* @controller: The controller for which to retrieve the bar number.
* @bar_number: This parameter depicts the BAR index/number to be read.
*
* Return a pointer value indicating the contents of the BAR. NULL indicates an
* invalid BAR index/number was specified. All other values indicate a valid
* VIRTUAL address from the BAR.
*/
void *scic_cb_pci_get_bar(
struct scic_sds_controller *controller,
u16 bar_number);
/**
* scic_cb_get_virtual_address() - This callback method asks the user to
* provide the virtual address for the supplied physical address.
* @controller: This parameter is the core controller object handle.
* @physical_address: This parameter is the physical address which is to be
* returned as a virtual address.
*
* The method returns the virtual address for the supplied physical address.
*/
void *scic_cb_get_virtual_address(
struct scic_sds_controller *controller,
dma_addr_t physical_address);
/**
* scic_cb_port_stop_complete() - This method informs the user when a stop
* operation on the port has completed.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
* @completion_status: This parameter specifies the status for the operation
* being completed.
*
*/
void scic_cb_port_stop_complete(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
enum sci_status completion_status);
/**
* scic_cb_port_hard_reset_complete() - This method informs the user when a
* hard reset on the port has completed. This hard reset could have been
* initiated by the user or by the remote port.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
* @completion_status: This parameter specifies the status for the operation
* being completed.
*
*/
void scic_cb_port_hard_reset_complete(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
enum sci_status completion_status);
/**
* scic_cb_port_ready() - This method informs the user that the port is now in
* a ready state and can be utilized to issue IOs.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
*
*/
void scic_cb_port_ready(
struct scic_sds_controller *controller,
struct scic_sds_port *port);
/**
* scic_cb_port_not_ready() - This method informs the user that the port is now
* not in a ready (i.e. busy) state and can't be utilized to issue IOs.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
* @reason_code: This parameter specifies the reason for the port not ready
* callback.
*
*/
void scic_cb_port_not_ready(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
u32 reason_code);
/**
* scic_cb_port_invalid_link_up() - 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.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
* @phy: This parameter specifies the phy that came ready, but the phy can't be
* a valid member of the port.
*
*/
void scic_cb_port_invalid_link_up(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy);
/**
* scic_cb_port_bc_change_primitive_received() - This callback method informs
* the user that a broadcast change primitive was received.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked. For instances where the phy on which the primitive was
* received is not part of a port, this parameter will be
* SCI_INVALID_HANDLE_T.
* @phy: This parameter specifies the phy on which the primitive was received.
*
*/
void scic_cb_port_bc_change_primitive_received(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy);
/**
* scic_cb_port_link_up() - This callback method informs the user that a phy
* has become operational and is capable of communicating with the remote
* end point.
* @controller: This parameter represents the controller associated with the
* phy.
* @port: This parameter specifies the port object for which the user callback
* is being invoked. There may be conditions where this parameter can be
* SCI_INVALID_HANDLE
* @phy: This parameter specifies the phy object for which the user callback is
* being invoked.
*
*/
void scic_cb_port_link_up(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy);
/**
* scic_cb_port_link_down() - This callback method informs the user that a phy
* is no longer operational and is not capable of communicating with the
* remote end point.
* @controller: This parameter represents the controller associated with the
* phy.
* @port: This parameter specifies the port object for which the user callback
* is being invoked. There may be conditions where this parameter can be
* SCI_INVALID_HANDLE
* @phy: This parameter specifies the phy object for which the user callback is
* being invoked.
*
*/
void scic_cb_port_link_down(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy);
/**
* scic_cb_remote_device_start_complete() - This user callback method will
* inform the user that a start operation has completed.
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the completion callback.
* @completion_status: This parameter specifies the completion status for the
* operation.
*
*/
void scic_cb_remote_device_start_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
enum sci_status completion_status);
/**
* scic_cb_remote_device_stop_complete() - This user callback method will
* inform the user that a stop operation has completed.
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the completion callback.
* @completion_status: This parameter specifies the completion status for the
* operation.
*
*/
void scic_cb_remote_device_stop_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
enum sci_status completion_status);
/**
* scic_cb_remote_device_ready() - This user callback method will inform the
* user that a remote device is now capable of handling IO requests.
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the callback.
*
*/
void scic_cb_remote_device_ready(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device);
/**
* scic_cb_remote_device_not_ready() - This user callback method will inform
* the user that a remote device is no longer capable of handling IO
* requests (until a ready callback is invoked).
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the callback.
* @reason_code: This paramete specifies the reason the remote device is not
* ready.
*
*/
void scic_cb_remote_device_not_ready(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
u32 reason_code);
#if !defined(DISABLE_ATAPI)
/**
* scic_cb_stp_packet_io_request_get_cdb_address() - This user callback gets
* from stp packet io's user request the CDB address.
* @scic_user_io_request:
*
* The cdb adress.
*/
void *scic_cb_stp_packet_io_request_get_cdb_address(
void *scic_user_io_request);
/**
* scic_cb_stp_packet_io_request_get_cdb_length() - This user callback gets
* from stp packet io's user request the CDB length.
* @scic_user_io_request:
*
* The cdb length.
*/
u32 scic_cb_stp_packet_io_request_get_cdb_length(
void *scic_user_io_request);
#else /* !defined(DISABLE_ATAPI) */
#define scic_cb_stp_packet_io_request_get_cdb_address(scic_user_io_request) NULL
#define scic_cb_stp_packet_io_request_get_cdb_length(scic_user_io_request) 0
#endif /* !defined(DISABLE_ATAPI) */
#endif /* _SCIC_USER_CALLBACK_H_ */

View File

@ -0,0 +1,280 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCU_COMPLETION_CODES_HEADER_
#define _SCU_COMPLETION_CODES_HEADER_
/**
* This file contains the constants and macros for the SCU hardware completion
* codes.
*
*
*/
#define SCU_COMPLETION_TYPE_SHIFT 28
#define SCU_COMPLETION_TYPE_MASK 0x70000000
/**
* SCU_COMPLETION_TYPE() -
*
* This macro constructs an SCU completion type
*/
#define SCU_COMPLETION_TYPE(type) \
((u32)(type) << SCU_COMPLETION_TYPE_SHIFT)
/**
* SCU_COMPLETION_TYPE() -
*
* These macros contain the SCU completion types SCU_COMPLETION_TYPE
*/
#define SCU_COMPLETION_TYPE_TASK SCU_COMPLETION_TYPE(0)
#define SCU_COMPLETION_TYPE_SDMA SCU_COMPLETION_TYPE(1)
#define SCU_COMPLETION_TYPE_UFI SCU_COMPLETION_TYPE(2)
#define SCU_COMPLETION_TYPE_EVENT SCU_COMPLETION_TYPE(3)
#define SCU_COMPLETION_TYPE_NOTIFY SCU_COMPLETION_TYPE(4)
/**
*
*
* These constants provide the shift and mask values for the various parts of
* an SCU completion code.
*/
#define SCU_COMPLETION_STATUS_MASK 0x0FFC0000
#define SCU_COMPLETION_TL_STATUS_MASK 0x0FC00000
#define SCU_COMPLETION_TL_STATUS_SHIFT 22
#define SCU_COMPLETION_SDMA_STATUS_MASK 0x003C0000
#define SCU_COMPLETION_PEG_MASK 0x00010000
#define SCU_COMPLETION_PORT_MASK 0x00007000
#define SCU_COMPLETION_PE_MASK SCU_COMPLETION_PORT_MASK
#define SCU_COMPLETION_PE_SHIFT 12
#define SCU_COMPLETION_INDEX_MASK 0x00000FFF
/**
* SCU_GET_COMPLETION_TYPE() -
*
* This macro returns the SCU completion type.
*/
#define SCU_GET_COMPLETION_TYPE(completion_code) \
((completion_code) & SCU_COMPLETION_TYPE_MASK)
/**
* SCU_GET_COMPLETION_STATUS() -
*
* This macro returns the SCU completion status.
*/
#define SCU_GET_COMPLETION_STATUS(completion_code) \
((completion_code) & SCU_COMPLETION_STATUS_MASK)
/**
* SCU_GET_COMPLETION_TL_STATUS() -
*
* This macro returns the transport layer completion status.
*/
#define SCU_GET_COMPLETION_TL_STATUS(completion_code) \
((completion_code) & SCU_COMPLETION_TL_STATUS_MASK)
/**
* SCU_MAKE_COMPLETION_STATUS() -
*
* This macro takes a completion code and performs the shift and mask
* operations to turn it into a completion code that can be compared to a
* SCU_GET_COMPLETION_TL_STATUS.
*/
#define SCU_MAKE_COMPLETION_STATUS(completion_code) \
((u32)(completion_code) << SCU_COMPLETION_TL_STATUS_SHIFT)
/**
* SCU_NORMALIZE_COMPLETION_STATUS() -
*
* This macro takes a SCU_GET_COMPLETION_TL_STATUS and normalizes it for a
* return code.
*/
#define SCU_NORMALIZE_COMPLETION_STATUS(completion_code) \
(\
((completion_code) & SCU_COMPLETION_TL_STATUS_MASK) \
>> SCU_COMPLETION_TL_STATUS_SHIFT \
)
/**
* SCU_GET_COMPLETION_SDMA_STATUS() -
*
* This macro returns the SDMA completion status.
*/
#define SCU_GET_COMPLETION_SDMA_STATUS(completion_code) \
((completion_code) & SCU_COMPLETION_SDMA_STATUS_MASK)
/**
* SCU_GET_COMPLETION_PEG() -
*
* This macro returns the Protocol Engine Group from the completion code.
*/
#define SCU_GET_COMPLETION_PEG(completion_code) \
((completion_code) & SCU_COMPLETION_PEG_MASK)
/**
* SCU_GET_COMPLETION_PORT() -
*
* This macro reuturns the logical port index from the completion code.
*/
#define SCU_GET_COMPLETION_PORT(completion_code) \
((completion_code) & SCU_COMPLETION_PORT_MASK)
/**
* SCU_GET_PROTOCOL_ENGINE_INDEX() -
*
* This macro returns the PE index from the completion code.
*/
#define SCU_GET_PROTOCOL_ENGINE_INDEX(completion_code) \
(((completion_code) & SCU_COMPLETION_PE_MASK) >> SCU_COMPLETION_PE_SHIFT)
/**
* SCU_GET_COMPLETION_INDEX() -
*
* This macro returns the index of the completion which is either a TCi or an
* RNi depending on the completion type.
*/
#define SCU_GET_COMPLETION_INDEX(completion_code) \
((completion_code) & SCU_COMPLETION_INDEX_MASK)
#define SCU_UNSOLICITED_FRAME_MASK 0x0FFF0000
#define SCU_UNSOLICITED_FRAME_SHIFT 16
/**
* SCU_GET_FRAME_INDEX() -
*
* This macro returns a normalized frame index from an unsolicited frame
* completion.
*/
#define SCU_GET_FRAME_INDEX(completion_code) \
(\
((completion_code) & SCU_UNSOLICITED_FRAME_MASK) \
>> SCU_UNSOLICITED_FRAME_SHIFT \
)
#define SCU_UNSOLICITED_FRAME_ERROR_MASK 0x00008000
/**
* SCU_GET_FRAME_ERROR() -
*
* This macro returns a zero (0) value if there is no frame error otherwise it
* returns non-zero (!0).
*/
#define SCU_GET_FRAME_ERROR(completion_code) \
((completion_code) & SCU_UNSOLICITED_FRAME_ERROR_MASK)
/**
*
*
* These constants represent normalized completion codes which must be shifted
* 18 bits to match it with the hardware completion code. In a 16-bit compiler,
* immediate constants are 16-bit values (the size of an int). If we shift
* those by 18 bits, we completely lose the value. To ensure the value is a
* 32-bit value like we want, each immediate value must be cast to a u32.
*/
#define SCU_TASK_DONE_GOOD ((u32)0x00)
#define SCU_TASK_DONE_CRC_ERR ((u32)0x14)
#define SCU_TASK_DONE_CHECK_RESPONSE ((u32)0x14)
#define SCU_TASK_DONE_GEN_RESPONSE ((u32)0x15)
#define SCU_TASK_DONE_NAK_CMD_ERR ((u32)0x16)
#define SCU_TASK_DONE_LL_R_ERR ((u32)0x17)
#define SCU_TASK_DONE_ACK_NAK_TO ((u32)0x17)
#define SCU_TASK_DONE_LL_PERR ((u32)0x18)
#define SCU_TASK_DONE_LL_SY_TERM ((u32)0x19)
#define SCU_TASK_DONE_NAK_ERR ((u32)0x19)
#define SCU_TASK_DONE_LL_LF_TERM ((u32)0x1A)
#define SCU_TASK_DONE_DATA_LEN_ERR ((u32)0x1A)
#define SCU_TASK_DONE_LL_CL_TERM ((u32)0x1B)
#define SCU_TASK_DONE_LL_ABORT_ERR ((u32)0x1B)
#define SCU_TASK_DONE_SEQ_INV_TYPE ((u32)0x1C)
#define SCU_TASK_DONE_UNEXP_XR ((u32)0x1C)
#define SCU_TASK_DONE_INV_FIS_TYPE ((u32)0x1D)
#define SCU_TASK_DONE_XR_IU_LEN_ERR ((u32)0x1D)
#define SCU_TASK_DONE_INV_FIS_LEN ((u32)0x1E)
#define SCU_TASK_DONE_XR_WD_LEN ((u32)0x1E)
#define SCU_TASK_DONE_SDMA_ERR ((u32)0x1F)
#define SCU_TASK_DONE_OFFSET_ERR ((u32)0x20)
#define SCU_TASK_DONE_MAX_PLD_ERR ((u32)0x21)
#define SCU_TASK_DONE_EXCESS_DATA ((u32)0x22)
#define SCU_TASK_DONE_LF_ERR ((u32)0x23)
#define SCU_TASK_DONE_UNEXP_FIS ((u32)0x24)
#define SCU_TASK_DONE_UNEXP_RESP ((u32)0x24)
#define SCU_TASK_DONE_EARLY_RESP ((u32)0x25)
#define SCU_TASK_DONE_SMP_RESP_TO_ERR ((u32)0x26)
#define SCU_TASK_DONE_DMASETUP_DIRERR ((u32)0x27)
#define SCU_TASK_DONE_SMP_UFI_ERR ((u32)0x27)
#define SCU_TASK_DONE_XFERCNT_ERR ((u32)0x28)
#define SCU_TASK_DONE_SMP_FRM_TYPE_ERR ((u32)0x28)
#define SCU_TASK_DONE_SMP_LL_RX_ERR ((u32)0x29)
#define SCU_TASK_DONE_RESP_LEN_ERR ((u32)0x2A)
#define SCU_TASK_DONE_UNEXP_DATA ((u32)0x2B)
#define SCU_TASK_DONE_OPEN_FAIL ((u32)0x2C)
#define SCU_TASK_DONE_UNEXP_SDBFIS ((u32)0x2D)
#define SCU_TASK_DONE_REG_ERR ((u32)0x2E)
#define SCU_TASK_DONE_SDB_ERR ((u32)0x2F)
#define SCU_TASK_DONE_TASK_ABORT ((u32)0x30)
#define SCU_TASK_OPEN_REJECT_WRONG_DESTINATION ((u32)0x34)
#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_1 ((u32)0x35)
#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_2 ((u32)0x36)
#define SCU_TASK_OPEN_REJECT_RESERVED_ABANDON_3 ((u32)0x37)
#define SCU_TASK_OPEN_REJECT_BAD_DESTINATION ((u32)0x38)
#define SCU_TASK_OPEN_REJECT_ZONE_VIOLATION ((u32)0x39)
#define SCU_TASK_DONE_VIIT_ENTRY_NV ((u32)0x3A)
#define SCU_TASK_DONE_IIT_ENTRY_NV ((u32)0x3B)
#define SCU_TASK_DONE_RNCNV_OUTBOUND ((u32)0x3C)
#define SCU_TASK_OPEN_REJECT_STP_RESOURCES_BUSY ((u32)0x3D)
#define SCU_TASK_OPEN_REJECT_PROTOCOL_NOT_SUPPORTED ((u32)0x3E)
#define SCU_TASK_OPEN_REJECT_CONNECTION_RATE_NOT_SUPPORTED ((u32)0x3F)
#endif /* _SCU_COMPLETION_CODES_HEADER_ */

View File

@ -0,0 +1,151 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCU_CONSTANTS_H_
#define _SCU_CONSTANTS_H_
/**
* This file contains the SCU hardware constants.
*
*
*/
#include "sci_controller_constants.h"
/**
*
*
* 2 indicates the maximum number of UFs that can occur for a given IO request.
* The hardware handles reception of additional unsolicited frames while all
* UFs are in use, by holding off the transmitting device. This number could
* be theoretically reduced to 1, but 2 provides for more reliable operation.
* During SATA PIO operation, it is possible under some conditions for there to
* be 3 separate FISes received, back to back to back (PIO Setup, Data, D2H
* Register). It is unlikely to have all 3 pending all at once without some of
* them already being processed.
*/
#define SCU_MIN_UNSOLICITED_FRAMES (1)
#define SCU_MIN_CRITICAL_NOTIFICATIONS (24)
#define SCU_MIN_EVENTS (4)
#define SCU_MIN_COMPLETION_QUEUE_SCRATCH (2)
#define SCU_MIN_COMPLETION_QUEUE_ENTRIES (SCU_MIN_CRITICAL_NOTIFICATIONS \
+ SCU_MIN_EVENTS \
+ SCU_MIN_UNSOLICITED_FRAMES \
+ SCI_MIN_IO_REQUESTS \
+ SCU_MIN_COMPLETION_QUEUE_SCRATCH)
#define SCU_MAX_CRITICAL_NOTIFICATIONS (384)
#define SCU_MAX_EVENTS (128)
#define SCU_MAX_UNSOLICITED_FRAMES (128)
#define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128)
#define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \
+ SCU_MAX_EVENTS \
+ SCU_MAX_UNSOLICITED_FRAMES \
+ SCI_MAX_IO_REQUESTS \
+ SCU_MAX_COMPLETION_QUEUE_SCRATCH)
#if !defined(ENABLE_MINIMUM_MEMORY_MODE)
#define SCU_UNSOLICITED_FRAME_COUNT SCU_MAX_UNSOLICITED_FRAMES
#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MAX_CRITICAL_NOTIFICATIONS
#define SCU_EVENT_COUNT SCU_MAX_EVENTS
#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MAX_COMPLETION_QUEUE_SCRATCH
#define SCU_IO_REQUEST_COUNT SCI_MAX_IO_REQUESTS
#define SCU_IO_REQUEST_SGE_COUNT SCI_MAX_SCATTER_GATHER_ELEMENTS
#define SCU_COMPLETION_QUEUE_COUNT SCU_MAX_COMPLETION_QUEUE_ENTRIES
#else
#define SCU_UNSOLICITED_FRAME_COUNT SCU_MIN_UNSOLICITED_FRAMES
#define SCU_CRITICAL_NOTIFICATION_COUNT SCU_MIN_CRITICAL_NOTIFICATIONS
#define SCU_EVENT_COUNT SCU_MIN_EVENTS
#define SCU_COMPLETION_QUEUE_SCRATCH SCU_MIN_COMPLETION_QUEUE_SCRATCH
#define SCU_IO_REQUEST_COUNT SCI_MIN_IO_REQUESTS
#define SCU_IO_REQUEST_SGE_COUNT SCI_MIN_SCATTER_GATHER_ELEMENTS
#define SCU_COMPLETION_QUEUE_COUNT SCU_MIN_COMPLETION_QUEUE_ENTRIES
#endif /* !defined(ENABLE_MINIMUM_MEMORY_OPERATION) */
/**
*
*
* The SCU_COMPLETION_QUEUE_COUNT constant indicates the size of the completion
* queue into which the hardware DMAs 32-bit quantas (completion entries).
*/
/**
*
*
* This queue must be programmed to a power of 2 size (e.g. 32, 64, 1024, etc.).
*/
#if (SCU_COMPLETION_QUEUE_COUNT != 16) && \
(SCU_COMPLETION_QUEUE_COUNT != 32) && \
(SCU_COMPLETION_QUEUE_COUNT != 64) && \
(SCU_COMPLETION_QUEUE_COUNT != 128) && \
(SCU_COMPLETION_QUEUE_COUNT != 256) && \
(SCU_COMPLETION_QUEUE_COUNT != 512) && \
(SCU_COMPLETION_QUEUE_COUNT != 1024)
#error "SCU_COMPLETION_QUEUE_COUNT must be set to a power of 2."
#endif
#if SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES
#error "Invalid configuration of unsolicited frame constants"
#endif /* SCU_MIN_UNSOLICITED_FRAMES > SCU_MAX_UNSOLICITED_FRAMES */
#define SCU_MIN_UF_TABLE_ENTRIES (8)
#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024)
#define SCU_INVALID_FRAME_INDEX (0xFFFF)
#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF)
#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF)
#endif /* _SCU_CONSTANTS_H_ */

View File

@ -0,0 +1,336 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SCU_EVENT_CODES_HEADER__
#define __SCU_EVENT_CODES_HEADER__
/**
* This file contains the constants and macros for the SCU event codes.
*
*
*/
#define SCU_EVENT_TYPE_CODE_SHIFT 24
#define SCU_EVENT_TYPE_CODE_MASK 0x0F000000
#define SCU_EVENT_SPECIFIC_CODE_SHIFT 18
#define SCU_EVENT_SPECIFIC_CODE_MASK 0x00FC0000
#define SCU_EVENT_CODE_MASK \
(SCU_EVENT_TYPE_CODE_MASK | SCU_EVENT_SPECIFIC_CODE_MASK)
/**
* SCU_EVENT_TYPE() -
*
* This macro constructs an SCU event type from the type value.
*/
#define SCU_EVENT_TYPE(type) \
((u32)(type) << SCU_EVENT_TYPE_CODE_SHIFT)
/**
* SCU_EVENT_SPECIFIC() -
*
* This macro constructs an SCU event specifier from the code value.
*/
#define SCU_EVENT_SPECIFIC(code) \
((u32)(code) << SCU_EVENT_SPECIFIC_CODE_SHIFT)
/**
* SCU_EVENT_MESSAGE() -
*
* This macro constructs a combines an SCU event type and SCU event specifier
* from the type and code values.
*/
#define SCU_EVENT_MESSAGE(type, code) \
((type) | SCU_EVENT_SPECIFIC(code))
/**
* SCU_EVENT_TYPE() -
*
* SCU_EVENT_TYPES
*/
#define SCU_EVENT_TYPE_SMU_COMMAND_ERROR SCU_EVENT_TYPE(0x08)
#define SCU_EVENT_TYPE_SMU_PCQ_ERROR SCU_EVENT_TYPE(0x09)
#define SCU_EVENT_TYPE_SMU_ERROR SCU_EVENT_TYPE(0x00)
#define SCU_EVENT_TYPE_TRANSPORT_ERROR SCU_EVENT_TYPE(0x01)
#define SCU_EVENT_TYPE_BROADCAST_CHANGE SCU_EVENT_TYPE(0x02)
#define SCU_EVENT_TYPE_OSSP_EVENT SCU_EVENT_TYPE(0x03)
#define SCU_EVENT_TYPE_FATAL_MEMORY_ERROR SCU_EVENT_TYPE(0x0F)
#define SCU_EVENT_TYPE_RNC_SUSPEND_TX SCU_EVENT_TYPE(0x04)
#define SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX SCU_EVENT_TYPE(0x05)
#define SCU_EVENT_TYPE_RNC_OPS_MISC SCU_EVENT_TYPE(0x06)
#define SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT SCU_EVENT_TYPE(0x07)
#define SCU_EVENT_TYPE_ERR_CNT_EVENT SCU_EVENT_TYPE(0x0A)
/**
*
*
* SCU_EVENT_SPECIFIERS
*/
#define SCU_EVENT_SPECIFIER_DRIVER_SUSPEND 0x20
#define SCU_EVENT_SPECIFIER_RNC_RELEASE 0x00
/**
*
*
* SMU_COMMAND_EVENTS
*/
#define SCU_EVENT_INVALID_CONTEXT_COMMAND \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_COMMAND_ERROR, 0x00)
/**
*
*
* SMU_PCQ_EVENTS
*/
#define SCU_EVENT_UNCORRECTABLE_PCQ_ERROR \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_PCQ_ERROR, 0x00)
/**
*
*
* SMU_EVENTS
*/
#define SCU_EVENT_UNCORRECTABLE_REGISTER_WRITE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x02)
#define SCU_EVENT_UNCORRECTABLE_REGISTER_READ \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x03)
#define SCU_EVENT_PCIE_INTERFACE_ERROR \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x04)
#define SCU_EVENT_FUNCTION_LEVEL_RESET \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_SMU_ERROR, 0x05)
/**
*
*
* TRANSPORT_LEVEL_ERRORS
*/
#define SCU_EVENT_ACK_NAK_TIMEOUT_ERROR \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_TRANSPORT_ERROR, 0x00)
/**
*
*
* BROADCAST_CHANGE_EVENTS
*/
#define SCU_EVENT_BROADCAST_CHANGE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x01)
#define SCU_EVENT_BROADCAST_RESERVED0 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x02)
#define SCU_EVENT_BROADCAST_RESERVED1 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x03)
#define SCU_EVENT_BROADCAST_SES \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x04)
#define SCU_EVENT_BROADCAST_EXPANDER \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x05)
#define SCU_EVENT_BROADCAST_AEN \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x06)
#define SCU_EVENT_BROADCAST_RESERVED3 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x07)
#define SCU_EVENT_BROADCAST_RESERVED4 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x08)
#define SCU_EVENT_PE_SUSPENDED \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_BROADCAST_CHANGE, 0x09)
/**
*
*
* OSSP_EVENTS
*/
#define SCU_EVENT_PORT_SELECTOR_DETECTED \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x10)
#define SCU_EVENT_SENT_PORT_SELECTION \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x11)
#define SCU_EVENT_HARD_RESET_TRANSMITTED \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x12)
#define SCU_EVENT_HARD_RESET_RECEIVED \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x13)
#define SCU_EVENT_RECEIVED_IDENTIFY_TIMEOUT \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x15)
#define SCU_EVENT_LINK_FAILURE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x16)
#define SCU_EVENT_SATA_SPINUP_HOLD \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x17)
#define SCU_EVENT_SAS_15_SSC \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x18)
#define SCU_EVENT_SAS_15 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x19)
#define SCU_EVENT_SAS_30_SSC \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1A)
#define SCU_EVENT_SAS_30 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1B)
#define SCU_EVENT_SAS_60_SSC \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1C)
#define SCU_EVENT_SAS_60 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1D)
#define SCU_EVENT_SATA_15_SSC \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1E)
#define SCU_EVENT_SATA_15 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x1F)
#define SCU_EVENT_SATA_30_SSC \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x20)
#define SCU_EVENT_SATA_30 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x21)
#define SCU_EVENT_SATA_60_SSC \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x22)
#define SCU_EVENT_SATA_60 \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x23)
#define SCU_EVENT_SAS_PHY_DETECTED \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x24)
#define SCU_EVENT_SATA_PHY_DETECTED \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_OSSP_EVENT, 0x25)
/**
*
*
* FATAL_INTERNAL_MEMORY_ERROR_EVENTS
*/
#define SCU_EVENT_TSC_RNSC_UNCORRECTABLE_ERROR \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x00)
#define SCU_EVENT_TC_RNC_UNCORRECTABLE_ERROR \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x01)
#define SCU_EVENT_ZPT_UNCORRECTABLE_ERROR \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_FATAL_MEMORY_ERROR, 0x02)
/**
*
*
* REMOTE_NODE_SUSPEND_EVENTS
*/
#define SCU_EVENT_TL_RNC_SUSPEND_TX \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x00)
#define SCU_EVENT_TL_RNC_SUSPEND_TX_RX \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x00)
#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX, 0x20)
#define SCU_EVENT_DRIVER_POST_RNC_SUSPEND_TX_RX \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_SUSPEND_TX_RX, 0x20)
/**
*
*
* REMOTE_NODE_MISC_EVENTS
*/
#define SCU_EVENT_POST_RCN_RELEASE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, SCU_EVENT_SPECIFIER_RNC_RELEASE)
#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_ENABLE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x01)
#define SCU_EVENT_POST_IT_NEXUS_LOSS_TIMER_DISABLE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x02)
#define SCU_EVENT_POST_RNC_COMPLETE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x03)
#define SCU_EVENT_POST_RNC_INVALIDATE_COMPLETE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_RNC_OPS_MISC, 0x04)
/**
*
*
* ERROR_COUNT_EVENT
*/
#define SCU_EVENT_RX_CREDIT_BLOCKED_RECEIVED \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x00)
#define SCU_EVENT_TX_DONE_CREDIT_TIMEOUT \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x01)
#define SCU_EVENT_RX_DONE_CREDIT_TIMEOUT \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_ERR_CNT_EVENT, 0x02)
/**
* scu_get_event_type() -
*
* This macro returns the SCU event type from the event code.
*/
#define scu_get_event_type(event_code) \
((event_code) & SCU_EVENT_TYPE_CODE_MASK)
/**
* scu_get_event_specifier() -
*
* This macro returns the SCU event specifier from the event code.
*/
#define scu_get_event_specifier(event_code) \
((event_code) & SCU_EVENT_SPECIFIC_CODE_MASK)
/**
* scu_get_event_code() -
*
* This macro returns the combined SCU event type and SCU event specifier from
* the event code.
*/
#define scu_get_event_code(event_code) \
((event_code) & SCU_EVENT_CODE_MASK)
/**
*
*
* PTS_SCHEDULE_EVENT
*/
#define SCU_EVENT_SMP_RESPONSE_NO_PE \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x00)
#define SCU_EVENT_SPECIFIC_SMP_RESPONSE_NO_PE \
scu_get_event_specifier(SCU_EVENT_SMP_RESPONSE_NO_PE)
#define SCU_EVENT_TASK_TIMEOUT \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x01)
#define SCU_EVENT_SPECIFIC_TASK_TIMEOUT \
scu_get_event_specifier(SCU_EVENT_TASK_TIMEOUT)
#define SCU_EVENT_IT_NEXUS_TIMEOUT \
SCU_EVENT_MESSAGE(SCU_EVENT_TYPE_PTX_SCHEDULE_EVENT, 0x02)
#define SCU_EVENT_SPECIFIC_IT_NEXUS_TIMEOUT \
scu_get_event_specifier(SCU_EVENT_IT_NEXUS_TIMEOUT)
#endif /* __SCU_EVENT_CODES_HEADER__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __SCU_REMOTE_NODE_CONTEXT_HEADER__
#define __SCU_REMOTE_NODE_CONTEXT_HEADER__
/**
* This file contains the structures and constatns used by the SCU hardware to
* describe a remote node context.
*
*
*/
#include "sci_types.h"
/**
* struct ssp_remote_node_context - This structure contains the SCU hardware
* definition for an SSP remote node.
*
*
*/
struct ssp_remote_node_context {
/* WORD 0 */
/**
* This field is the remote node index assigned for this remote node. All
* remote nodes must have a unique remote node index. The value of the remote
* node index can not exceed the maximum number of remote nodes reported in
* the SCU device context capacity register.
*/
u32 remote_node_index:12;
u32 reserved0_1:4;
/**
* This field tells the SCU hardware how many simultaneous connections that
* this remote node will support.
*/
u32 remote_node_port_width:4;
/**
* This field tells the SCU hardware which logical port to associate with this
* remote node.
*/
u32 logical_port_index:3;
u32 reserved0_2:5;
/**
* This field will enable the I_T nexus loss timer for this remote node.
*/
u32 nexus_loss_timer_enable:1;
/**
* This field is the for driver debug only and is not used.
*/
u32 check_bit:1;
/**
* This field must be set to true when the hardware DMAs the remote node
* context to the hardware SRAM. When the remote node is being invalidated
* this field must be set to false.
*/
u32 is_valid:1;
/**
* This field must be set to true.
*/
u32 is_remote_node_context:1;
/* WORD 1 - 2 */
/**
* This is the low word of the remote device SAS Address
*/
u32 remote_sas_address_lo;
/**
* This field is the high word of the remote device SAS Address
*/
u32 remote_sas_address_hi;
/* WORD 3 */
/**
* This field reprensets the function number assigned to this remote device.
* This value must match the virtual function number that is being used to
* communicate to the device.
*/
u32 function_number:8;
u32 reserved3_1:8;
/**
* This field provides the driver a way to cheat on the arbitration wait time
* for this remote node.
*/
u32 arbitration_wait_time:16;
/* WORD 4 */
/**
* This field tells the SCU hardware how long this device may occupy the
* connection before it must be closed.
*/
u32 connection_occupancy_timeout:16;
/**
* This field tells the SCU hardware how long to maintain a connection when
* there are no frames being transmitted on the link.
*/
u32 connection_inactivity_timeout:16;
/* WORD 5 */
/**
* This field allows the driver to cheat on the arbitration wait time for this
* remote node.
*/
u32 initial_arbitration_wait_time:16;
/**
* This field is tells the hardware what to program for the connection rate in
* the open address frame. See the SAS spec for valid values.
*/
u32 oaf_connection_rate:4;
/**
* This field tells the SCU hardware what to program for the features in the
* open address frame. See the SAS spec for valid values.
*/
u32 oaf_features:4;
/**
* This field tells the SCU hardware what to use for the source zone group in
* the open address frame. See the SAS spec for more details on zoning.
*/
u32 oaf_source_zone_group:8;
/* WORD 6 */
/**
* This field tells the SCU hardware what to use as the more capibilities in
* the open address frame. See the SAS Spec for details.
*/
u32 oaf_more_compatibility_features;
/* WORD 7 */
u32 reserved7;
};
/**
* struct stp_remote_node_context - This structure contains the SCU hardware
* definition for a STP remote node.
*
* STP Targets are not yet supported so this definition is a placeholder until
* we do support them.
*/
struct stp_remote_node_context {
/**
* Placeholder data for the STP remote node.
*/
u32 data[8];
};
/**
* This union combines the SAS and SATA remote node definitions.
*
* union scu_remote_node_context
*/
union scu_remote_node_context {
/**
* SSP Remote Node
*/
struct ssp_remote_node_context ssp;
/**
* STP Remote Node
*/
struct stp_remote_node_context stp;
};
#endif /* __SCU_REMOTE_NODE_CONTEXT_HEADER__ */

View File

@ -0,0 +1,943 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCU_TASK_CONTEXT_H_
#define _SCU_TASK_CONTEXT_H_
/**
* This file contains the structures and constants for the SCU hardware task
* context.
*
*
*/
#include "sci_types.h"
/**
* enum SCU_SSP_TASK_TYPE - This enumberation defines the various SSP task
* types the SCU hardware will accept. The definition for the various task
* types the SCU hardware will accept can be found in the DS specification.
*
*
*/
typedef enum {
SCU_TASK_TYPE_IOREAD, /* /< IO READ direction or no direction */
SCU_TASK_TYPE_IOWRITE, /* /< IO Write direction */
SCU_TASK_TYPE_SMP_REQUEST, /* /< SMP Request type */
SCU_TASK_TYPE_RESPONSE, /* /< Driver generated response frame (targt mode) */
SCU_TASK_TYPE_RAW_FRAME, /* /< Raw frame request type */
SCU_TASK_TYPE_PRIMITIVE /* /< Request for a primitive to be transmitted */
} SCU_SSP_TASK_TYPE;
/**
* enum SCU_SATA_TASK_TYPE - This enumeration defines the various SATA task
* types the SCU hardware will accept. The definition for the various task
* types the SCU hardware will accept can be found in the DS specification.
*
*
*/
typedef enum {
SCU_TASK_TYPE_DMA_IN, /* /< Read request */
SCU_TASK_TYPE_FPDMAQ_READ, /* /< NCQ read request */
SCU_TASK_TYPE_PACKET_DMA_IN, /* /< Packet read request */
SCU_TASK_TYPE_SATA_RAW_FRAME, /* /< Raw frame request */
RESERVED_4,
RESERVED_5,
RESERVED_6,
RESERVED_7,
SCU_TASK_TYPE_DMA_OUT, /* /< Write request */
SCU_TASK_TYPE_FPDMAQ_WRITE, /* /< NCQ write Request */
SCU_TASK_TYPE_PACKET_DMA_OUT /* /< Packet write request */
} SCU_SATA_TASK_TYPE;
/**
*
*
* SCU_CONTEXT_TYPE
*/
#define SCU_TASK_CONTEXT_TYPE 0
#define SCU_RNC_CONTEXT_TYPE 1
/**
*
*
* SCU_TASK_CONTEXT_VALIDITY
*/
#define SCU_TASK_CONTEXT_INVALID 0
#define SCU_TASK_CONTEXT_VALID 1
/**
*
*
* SCU_COMMAND_CODE
*/
#define SCU_COMMAND_CODE_INITIATOR_NEW_TASK 0
#define SCU_COMMAND_CODE_ACTIVE_TASK 1
#define SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK 2
#define SCU_COMMAND_CODE_TARGET_RAW_FRAMES 3
/**
*
*
* SCU_TASK_PRIORITY
*/
/**
*
*
* This priority is used when there is no priority request for this request.
*/
#define SCU_TASK_PRIORITY_NORMAL 0
/**
*
*
* This priority indicates that the task should be scheduled to the head of the
* queue. The task will NOT be executed if the TX is suspended for the remote
* node.
*/
#define SCU_TASK_PRIORITY_HEAD_OF_Q 1
/**
*
*
* This priority indicates that the task will be executed before all
* SCU_TASK_PRIORITY_NORMAL and SCU_TASK_PRIORITY_HEAD_OF_Q tasks. The task
* WILL be executed if the TX is suspended for the remote node.
*/
#define SCU_TASK_PRIORITY_HIGH 2
/**
*
*
* This task priority is reserved and should not be used.
*/
#define SCU_TASK_PRIORITY_RESERVED 3
#define SCU_TASK_INITIATOR_MODE 1
#define SCU_TASK_TARGET_MODE 0
#define SCU_TASK_REGULAR 0
#define SCU_TASK_ABORTED 1
/* direction bit defintion */
/**
*
*
* SATA_DIRECTION
*/
#define SCU_SATA_WRITE_DATA_DIRECTION 0
#define SCU_SATA_READ_DATA_DIRECTION 1
/**
*
*
* SCU_COMMAND_CONTEXT_MACROS These macros provide the mask and shift
* operations to construct the various SCU commands
*/
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT 21
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK 0x00E00000
#define scu_get_command_request_type(x) \
((x) & SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK)
#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT 18
#define SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK 0x001C0000
#define scu_get_command_request_subtype(x) \
((x) & SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK)
#define SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK \
(\
SCU_CONTEXT_COMMAND_REQUEST_TYPE_MASK \
| SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_MASK \
)
#define scu_get_command_request_full_type(x) \
((x) & SCU_CONTEXT_COMMAND_REQUEST_FULLTYPE_MASK)
#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_SHIFT 16
#define SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK 0x00010000
#define scu_get_command_protocl_engine_group(x) \
((x) & SCU_CONTEXT_COMMAND_PROTOCOL_ENGINE_GROUP_MASK)
#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_SHIFT 12
#define SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK 0x00007000
#define scu_get_command_reqeust_logical_port(x) \
((x) & SCU_CONTEXT_COMMAND_LOGICAL_PORT_MASK)
#define MAKE_SCU_CONTEXT_COMMAND_TYPE(type) \
((u32)(type) << SCU_CONTEXT_COMMAND_REQUEST_TYPE_SHIFT)
/**
* MAKE_SCU_CONTEXT_COMMAND_TYPE() -
*
* SCU_COMMAND_TYPES These constants provide the grouping of the different SCU
* command types.
*/
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(0)
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC MAKE_SCU_CONTEXT_COMMAND_TYPE(1)
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(2)
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(3)
#define SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC MAKE_SCU_CONTEXT_COMMAND_TYPE(6)
#define MAKE_SCU_CONTEXT_COMMAND_REQUEST(type, command) \
((type) | ((command) << SCU_CONTEXT_COMMAND_REQUEST_SUBTYPE_SHIFT))
/**
*
*
* SCU_REQUEST_TYPES These constants are the various request types that can be
* posted to the SCU hardware.
*/
#define SCU_CONTEXT_COMMAND_REQUST_POST_TC \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 0))
#define SCU_CONTEXT_COMMAND_REQUEST_POST_TC_ABORT \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_TC, 1))
#define SCU_CONTEXT_COMMAND_REQUST_DUMP_TC \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_TC, 0))
#define SCU_CONTEXT_COMMAND_POST_RNC_32 \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 0))
#define SCU_CONTEXT_COMMAND_POST_RNC_96 \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 1))
#define SCU_CONTEXT_COMMAND_POST_RNC_INVALIDATE \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_POST_RNC, 2))
#define SCU_CONTEXT_COMMAND_DUMP_RNC_32 \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 0))
#define SCU_CONTEXT_COMMAND_DUMP_RNC_96 \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_DUMP_RNC, 1))
#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 0))
#define SCU_CONTEXT_COMMAND_POST_RNC_SUSPEND_TX_RX \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 1))
#define SCU_CONTEXT_COMMAND_POST_RNC_RESUME \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 2))
#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_ENABLE \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 3))
#define SCU_CONTEXT_IT_NEXUS_LOSS_TIMER_DISABLE \
(MAKE_SCU_CONTEXT_COMMAND_REQUEST(SCU_CONTEXT_COMMAND_REQUEST_TYPE_OTHER_RNC, 4))
/**
*
*
* SCU_TASK_CONTEXT_PROTOCOL SCU Task context protocol types this is uesd to
* program the SCU Task context protocol field in word 0x00.
*/
#define SCU_TASK_CONTEXT_PROTOCOL_SMP 0x00
#define SCU_TASK_CONTEXT_PROTOCOL_SSP 0x01
#define SCU_TASK_CONTEXT_PROTOCOL_STP 0x02
#define SCU_TASK_CONTEXT_PROTOCOL_NONE 0x07
/**
* struct SSP_TASK_CONTEXT - This is the SCU hardware definition for an SSP
* request.
*
*
*/
struct SSP_TASK_CONTEXT {
/* OFFSET 0x18 */
u32 reserved00:24;
u32 frame_type:8;
/* OFFSET 0x1C */
u32 reserved01;
/* OFFSET 0x20 */
u32 fill_bytes:2;
u32 reserved02:6;
u32 changing_data_pointer:1;
u32 retransmit:1;
u32 retry_data_frame:1;
u32 tlr_control:2;
u32 reserved03:19;
/* OFFSET 0x24 */
u32 uiRsvd4;
/* OFFSET 0x28 */
u32 target_port_transfer_tag:16;
u32 tag:16;
/* OFFSET 0x2C */
u32 data_offset;
};
/**
* struct STP_TASK_CONTEXT - This is the SCU hardware definition for an STP
* request.
*
*
*/
struct STP_TASK_CONTEXT {
/* OFFSET 0x18 */
u32 fis_type:8;
u32 pm_port:4;
u32 reserved0:3;
u32 control:1;
u32 command:8;
u32 features:8;
/* OFFSET 0x1C */
u32 reserved1;
/* OFFSET 0x20 */
u32 reserved2;
/* OFFSET 0x24 */
u32 reserved3;
/* OFFSET 0x28 */
u32 ncq_tag:5;
u32 reserved4:27;
/* OFFSET 0x2C */
u32 data_offset; /* TODO: What is this used for? */
};
/**
* struct SMP_TASK_CONTEXT - This is the SCU hardware definition for an SMP
* request.
*
*
*/
struct SMP_TASK_CONTEXT {
/* OFFSET 0x18 */
u32 response_length:8;
u32 function_result:8;
u32 function:8;
u32 frame_type:8;
/* OFFSET 0x1C */
u32 smp_response_ufi:12;
u32 reserved1:20;
/* OFFSET 0x20 */
u32 reserved2;
/* OFFSET 0x24 */
u32 reserved3;
/* OFFSET 0x28 */
u32 reserved4;
/* OFFSET 0x2C */
u32 reserved5;
};
/**
* struct PRIMITIVE_TASK_CONTEXT - This is the SCU hardware definition used
* when the driver wants to send a primitive on the link.
*
*
*/
struct PRIMITIVE_TASK_CONTEXT {
/* OFFSET 0x18 */
/**
* This field is the control word and it must be 0.
*/
u32 control; /* /< must be set to 0 */
/* OFFSET 0x1C */
/**
* This field specifies the primitive that is to be transmitted.
*/
u32 sequence;
/* OFFSET 0x20 */
u32 reserved0;
/* OFFSET 0x24 */
u32 reserved1;
/* OFFSET 0x28 */
u32 reserved2;
/* OFFSET 0x2C */
u32 reserved3;
};
/**
* The union of the protocols that can be selected in the SCU task context
* field.
*
* PROTOCOL_CONTEXT
*/
union PROTOCOL_CONTEXT {
struct SSP_TASK_CONTEXT ssp;
struct STP_TASK_CONTEXT stp;
struct SMP_TASK_CONTEXT smp;
struct PRIMITIVE_TASK_CONTEXT primitive;
u32 words[6];
};
/**
* struct scu_sgl_element - This structure represents a single SCU defined SGL
* element. SCU SGLs contain a 64 bit address with the maximum data transfer
* being 24 bits in size. The SGL can not cross a 4GB boundary.
*
* struct scu_sgl_element
*/
struct scu_sgl_element {
/**
* This field is the upper 32 bits of the 64 bit physical address.
*/
u32 address_upper;
/**
* This field is the lower 32 bits of the 64 bit physical address.
*/
u32 address_lower;
/**
* This field is the number of bytes to transfer.
*/
u32 length:24;
/**
* This field is the address modifier to be used when a virtual function is
* requesting a data transfer.
*/
u32 address_modifier:8;
};
#define SCU_SGL_ELEMENT_PAIR_A 0
#define SCU_SGL_ELEMENT_PAIR_B 1
/**
* struct scu_sgl_element_pair - This structure is the SCU hardware definition
* of a pair of SGL elements. The SCU hardware always works on SGL pairs.
* They are refered to in the DS specification as SGL A and SGL B. Each SGL
* pair is followed by the address of the next pair.
*
*
*/
struct scu_sgl_element_pair {
/* OFFSET 0x60-0x68 */
/**
* This field is the SGL element A of the SGL pair.
*/
struct scu_sgl_element A;
/* OFFSET 0x6C-0x74 */
/**
* This field is the SGL element B of the SGL pair.
*/
struct scu_sgl_element B;
/* OFFSET 0x78-0x7C */
/**
* This field is the upper 32 bits of the 64 bit address to the next SGL
* element pair.
*/
u32 next_pair_upper;
/**
* This field is the lower 32 bits of the 64 bit address to the next SGL
* element pair.
*/
u32 next_pair_lower;
};
/**
* struct TRANSPORT_SNAPSHOT - This structure is the SCU hardware scratch area
* for the task context. This is set to 0 by the driver but can be read by
* issuing a dump TC request to the SCU.
*
*
*/
struct TRANSPORT_SNAPSHOT {
/* OFFSET 0x48 */
u32 xfer_rdy_write_data_length;
/* OFFSET 0x4C */
u32 data_offset;
/* OFFSET 0x50 */
u32 data_transfer_size:24;
u32 reserved_50_0:8;
/* OFFSET 0x54 */
u32 next_initiator_write_data_offset;
/* OFFSET 0x58 */
u32 next_initiator_write_data_xfer_size:24;
u32 reserved_58_0:8;
};
/**
* struct scu_task_context - This structure defines the contents of the SCU
* silicon task context. It lays out all of the fields according to the
* expected order and location for the Storage Controller unit.
*
*
*/
struct scu_task_context {
/* OFFSET 0x00 ------ */
/**
* This field must be encoded to one of the valid SCU task priority values
* - SCU_TASK_PRIORITY_NORMAL
* - SCU_TASK_PRIORITY_HEAD_OF_Q
* - SCU_TASK_PRIORITY_HIGH
*/
u32 priority:2;
/**
* This field must be set to true if this is an initiator generated request.
* Until target mode is supported all task requests are initiator requests.
*/
u32 initiator_request:1;
/**
* This field must be set to one of the valid connection rates valid values
* are 0x8, 0x9, and 0xA.
*/
u32 connection_rate:4;
/**
* This field muse be programed when generating an SMP response since the SMP
* connection remains open until the SMP response is generated.
*/
u32 protocol_engine_index:3;
/**
* This field must contain the logical port for the task request.
*/
u32 logical_port_index:3;
/**
* This field must be set to one of the SCU_TASK_CONTEXT_PROTOCOL values
* - SCU_TASK_CONTEXT_PROTOCOL_SMP
* - SCU_TASK_CONTEXT_PROTOCOL_SSP
* - SCU_TASK_CONTEXT_PROTOCOL_STP
* - SCU_TASK_CONTEXT_PROTOCOL_NONE
*/
u32 protocol_type:3;
/**
* This filed must be set to the TCi allocated for this task
*/
u32 task_index:12;
/**
* This field is reserved and must be set to 0x00
*/
u32 reserved_00_0:1;
/**
* For a normal task request this must be set to 0. If this is an abort of
* this task request it must be set to 1.
*/
u32 abort:1;
/**
* This field must be set to true for the SCU hardware to process the task.
*/
u32 valid:1;
/**
* This field must be set to SCU_TASK_CONTEXT_TYPE
*/
u32 context_type:1;
/* OFFSET 0x04 */
/**
* This field contains the RNi that is the target of this request.
*/
u32 remote_node_index:12;
/**
* This field is programmed if this is a mirrored request, which we are not
* using, in which case it is the RNi for the mirrored target.
*/
u32 mirrored_node_index:12;
/**
* This field is programmed with the direction of the SATA reqeust
* - SCU_SATA_WRITE_DATA_DIRECTION
* - SCU_SATA_READ_DATA_DIRECTION
*/
u32 sata_direction:1;
/**
* This field is programmsed with one of the following SCU_COMMAND_CODE
* - SCU_COMMAND_CODE_INITIATOR_NEW_TASK
* - SCU_COMMAND_CODE_ACTIVE_TASK
* - SCU_COMMAND_CODE_PRIMITIVE_SEQ_TASK
* - SCU_COMMAND_CODE_TARGET_RAW_FRAMES
*/
u32 command_code:2;
/**
* This field is set to true if the remote node should be suspended.
* This bit is only valid for SSP & SMP target devices.
*/
u32 suspend_node:1;
/**
* This field is programmed with one of the following command type codes
*
* For SAS requests use the SCU_SSP_TASK_TYPE
* - SCU_TASK_TYPE_IOREAD
* - SCU_TASK_TYPE_IOWRITE
* - SCU_TASK_TYPE_SMP_REQUEST
* - SCU_TASK_TYPE_RESPONSE
* - SCU_TASK_TYPE_RAW_FRAME
* - SCU_TASK_TYPE_PRIMITIVE
*
* For SATA requests use the SCU_SATA_TASK_TYPE
* - SCU_TASK_TYPE_DMA_IN
* - SCU_TASK_TYPE_FPDMAQ_READ
* - SCU_TASK_TYPE_PACKET_DMA_IN
* - SCU_TASK_TYPE_SATA_RAW_FRAME
* - SCU_TASK_TYPE_DMA_OUT
* - SCU_TASK_TYPE_FPDMAQ_WRITE
* - SCU_TASK_TYPE_PACKET_DMA_OUT
*/
u32 task_type:4;
/* OFFSET 0x08 */
/**
* This field is reserved and the must be set to 0x00
*/
u32 link_layer_control:8; /* presently all reserved */
/**
* This field is set to true when TLR is to be enabled
*/
u32 ssp_tlr_enable:1;
/**
* This is field specifies if the SCU DMAs a response frame to host
* memory for good response frames when operating in target mode.
*/
u32 dma_ssp_target_good_response:1;
/**
* This field indicates if the SCU should DMA the response frame to
* host memory.
*/
u32 do_not_dma_ssp_good_response:1;
/**
* This field is set to true when strict ordering is to be enabled
*/
u32 strict_ordering:1;
/**
* This field indicates the type of endianess to be utilized for the
* frame. command, task, and response frames utilized control_frame
* set to 1.
*/
u32 control_frame:1;
/**
* This field is reserved and the driver should set to 0x00
*/
u32 tl_control_reserved:3;
/**
* This field is set to true when the SCU hardware task timeout control is to
* be enabled
*/
u32 timeout_enable:1;
/**
* This field is reserved and the driver should set it to 0x00
*/
u32 pts_control_reserved:7;
/**
* This field should be set to true when block guard is to be enabled
*/
u32 block_guard_enable:1;
/**
* This field is reserved and the driver should set to 0x00
*/
u32 sdma_control_reserved:7;
/* OFFSET 0x0C */
/**
* This field is the address modifier for this io request it should be
* programmed with the virtual function that is making the request.
*/
u32 address_modifier:16;
/**
* @todo What we support mirrored SMP response frame?
*/
u32 mirrored_protocol_engine:3; /* mirrored protocol Engine Index */
/**
* If this is a mirrored request the logical port index for the mirrored RNi
* must be programmed.
*/
u32 mirrored_logical_port:4; /* mirrored local port index */
/**
* This field is reserved and the driver must set it to 0x00
*/
u32 reserved_0C_0:8;
/**
* This field must be set to true if the mirrored request processing is to be
* enabled.
*/
u32 mirror_request_enable:1; /* Mirrored request Enable */
/* OFFSET 0x10 */
/**
* This field is the command iu length in dwords
*/
u32 ssp_command_iu_length:8;
/**
* This is the target TLR enable bit it must be set to 0 when creatning the
* task context.
*/
u32 xfer_ready_tlr_enable:1;
/**
* This field is reserved and the driver must set it to 0x00
*/
u32 reserved_10_0:7;
/**
* This is the maximum burst size that the SCU hardware will send in one
* connection its value is (N x 512) and N must be a multiple of 2. If the
* value is 0x00 then maximum burst size is disabled.
*/
u32 ssp_max_burst_size:16;
/* OFFSET 0x14 */
/**
* This filed is set to the number of bytes to be transfered in the request.
*/
u32 transfer_length_bytes:24; /* In terms of bytes */
/**
* This field is reserved and the driver should set it to 0x00
*/
u32 reserved_14_0:8;
/* OFFSET 0x18-0x2C */
/**
* This union provides for the protocol specif part of the SCU Task Context.
*/
union PROTOCOL_CONTEXT type;
/* OFFSET 0x30-0x34 */
/**
* This field is the upper 32 bits of the 64 bit physical address of the
* command iu buffer
*/
u32 command_iu_upper;
/**
* This field is the lower 32 bits of the 64 bit physical address of the
* command iu buffer
*/
u32 command_iu_lower;
/* OFFSET 0x38-0x3C */
/**
* This field is the upper 32 bits of the 64 bit physical address of the
* response iu buffer
*/
u32 response_iu_upper;
/**
* This field is the lower 32 bits of the 64 bit physical address of the
* response iu buffer
*/
u32 response_iu_lower;
/* OFFSET 0x40 */
/**
* This field is set to the task phase of the SCU hardware. The driver must
* set this to 0x01
*/
u32 task_phase:8;
/**
* This field is set to the transport layer task status. The driver must set
* this to 0x00
*/
u32 task_status:8;
/**
* This field is used during initiator write TLR
*/
u32 previous_extended_tag:4;
/**
* This field is set the maximum number of retries for a STP non-data FIS
*/
u32 stp_retry_count:2;
/**
* This field is reserved and the driver must set it to 0x00
*/
u32 reserved_40_1:2;
/**
* This field is used by the SCU TL to determine when to take a snapshot when
* tranmitting read data frames.
* - 0x00 The entire IO
* - 0x01 32k
* - 0x02 64k
* - 0x04 128k
* - 0x08 256k
*/
u32 ssp_tlr_threshold:4;
/**
* This field is reserved and the driver must set it to 0x00
*/
u32 reserved_40_2:4;
/* OFFSET 0x44 */
u32 write_data_length; /* read only set to 0 */
/* OFFSET 0x48-0x58 */
struct TRANSPORT_SNAPSHOT snapshot; /* read only set to 0 */
/* OFFSET 0x5C */
u32 block_protection_enable:1;
u32 block_size:2;
u32 block_protection_function:2;
u32 reserved_5C_0:9;
u32 active_sgl_element:2; /* read only set to 0 */
u32 sgl_exhausted:1; /* read only set to 0 */
u32 payload_data_transfer_error:4; /* read only set to 0 */
u32 frame_buffer_offset:11; /* read only set to 0 */
/* OFFSET 0x60-0x7C */
/**
* This field is the first SGL element pair found in the TC data structure.
*/
struct scu_sgl_element_pair sgl_pair_ab;
/* OFFSET 0x80-0x9C */
/**
* This field is the second SGL element pair found in the TC data structure.
*/
struct scu_sgl_element_pair sgl_pair_cd;
/* OFFSET 0xA0-BC */
struct scu_sgl_element_pair sgl_snapshot_ac;
/* OFFSET 0xC0 */
u32 active_sgl_element_pair; /* read only set to 0 */
/* OFFSET 0xC4-0xCC */
u32 reserved_C4_CC[3];
/* OFFSET 0xD0 */
u32 intermediate_crc_value:16;
u32 initial_crc_seed:16;
/* OFFSET 0xD4 */
u32 application_tag_for_verify:16;
u32 application_tag_for_generate:16;
/* OFFSET 0xD8 */
u32 reference_tag_seed_for_verify_function;
/* OFFSET 0xDC */
u32 reserved_DC;
/* OFFSET 0xE0 */
u32 reserved_E0_0:16;
u32 application_tag_mask_for_generate:16;
/* OFFSET 0xE4 */
u32 block_protection_control:16;
u32 application_tag_mask_for_verify:16;
/* OFFSET 0xE8 */
u32 block_protection_error:8;
u32 reserved_E8_0:24;
/* OFFSET 0xEC */
u32 reference_tag_seed_for_verify;
/* OFFSET 0xF0 */
u32 intermediate_crc_valid_snapshot:16;
u32 reserved_F0_0:16;
/* OFFSET 0xF4 */
u32 reference_tag_seed_for_verify_function_snapshot;
/* OFFSET 0xF8 */
u32 snapshot_of_reserved_dword_DC_of_tc;
/* OFFSET 0xFC */
u32 reference_tag_seed_for_generate_function_snapshot;
};
#endif /* _SCU_TASK_CONTEXT_H_ */

View File

@ -0,0 +1,117 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This field defines the SCU format of an unsolicited frame (UF). A UF is a
* frame received by the SCU for which there is no known corresponding task
* context (TC).
*
*
*/
#ifndef _SCU_UNSOLICITED_FRAME_H_
#define _SCU_UNSOLICITED_FRAME_H_
#include "sci_types.h"
/**
*
*
* This constant defines the number of DWORDS found the unsolicited frame
* header data member.
*/
#define SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS 15
/**
* struct scu_unsolicited_frame_header -
*
* This structure delineates the format of an unsolicited frame header. The
* first DWORD are UF attributes defined by the silicon architecture. The data
* depicts actual header information received on the link.
*/
struct scu_unsolicited_frame_header {
/**
* This field indicates if there is an Initiator Index Table entry with
* which this header is associated.
*/
u32 iit_exists:1;
/**
* This field simply indicates the protocol type (i.e. SSP, STP, SMP).
*/
u32 protocol_type:3;
/**
* This field indicates if the frame is an address frame (IAF or OAF)
* or if it is a information unit frame.
*/
u32 is_address_frame:1;
/**
* This field simply indicates the connection rate at which the frame
* was received.
*/
u32 connection_rate:4;
u32 reserved:23;
/**
* This field represents the actual header data received on the link.
*/
u32 data[SCU_UNSOLICITED_FRAME_HEADER_DATA_DWORDS];
};
#endif /* _SCU_UNSOLICITED_FRAME_H_ */

View File

@ -0,0 +1,179 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCU_VIIT_DATA_HEADER_
#define _SCU_VIIT_DATA_HEADER_
/**
* This file contains the constants and structures for the SCU hardware VIIT
* table entries.
*
*
*/
#include "sci_types.h"
#define SCU_VIIT_ENTRY_ID_MASK (0xC0000000)
#define SCU_VIIT_ENTRY_ID_SHIFT (30)
#define SCU_VIIT_ENTRY_FUNCTION_MASK (0x0FF00000)
#define SCU_VIIT_ENTRY_FUNCTION_SHIFT (20)
#define SCU_VIIT_ENTRY_IPPTMODE_MASK (0x0001F800)
#define SCU_VIIT_ENTRY_IPPTMODE_SHIFT (12)
#define SCU_VIIT_ENTRY_LPVIE_MASK (0x00000F00)
#define SCU_VIIT_ENTRY_LPVIE_SHIFT (8)
#define SCU_VIIT_ENTRY_STATUS_MASK (0x000000FF)
#define SCU_VIIT_ENTRY_STATUS_SHIFT (0)
#define SCU_VIIT_ENTRY_ID_INVALID (0 << SCU_VIIT_ENTRY_ID_SHIFT)
#define SCU_VIIT_ENTRY_ID_VIIT (1 << SCU_VIIT_ENTRY_ID_SHIFT)
#define SCU_VIIT_ENTRY_ID_IIT (2 << SCU_VIIT_ENTRY_ID_SHIFT)
#define SCU_VIIT_ENTRY_ID_VIRT_EXP (3 << SCU_VIIT_ENTRY_ID_SHIFT)
#define SCU_VIIT_IPPT_SSP_INITIATOR (0x01 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
#define SCU_VIIT_IPPT_SMP_INITIATOR (0x02 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
#define SCU_VIIT_IPPT_STP_INITIATOR (0x04 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
#define SCU_VIIT_IPPT_INITIATOR \
(\
SCU_VIIT_IPPT_SSP_INITIATOR \
| SCU_VIIT_IPPT_SMP_INITIATOR \
| SCU_VIIT_IPPT_STP_INITIATOR \
)
#define SCU_VIIT_STATUS_RNC_VALID (0x01 << SCU_VIIT_ENTRY_STATUS_SHIFT)
#define SCU_VIIT_STATUS_ADDRESS_VALID (0x02 << SCU_VIIT_ENTRY_STATUS_SHIFT)
#define SCU_VIIT_STATUS_RNI_VALID (0x04 << SCU_VIIT_ENTRY_STATUS_SHIFT)
#define SCU_VIIT_STATUS_ALL_VALID \
(\
SCU_VIIT_STATUS_RNC_VALID \
| SCU_VIIT_STATUS_ADDRESS_VALID \
| SCU_VIIT_STATUS_RNI_VALID \
)
#define SCU_VIIT_IPPT_SMP_TARGET (0x10 << SCU_VIIT_ENTRY_IPPTMODE_SHIFT)
/**
* struct scu_viit_entry - This is the SCU Virtual Initiator Table Entry
*
*
*/
struct scu_viit_entry {
/**
* This must be encoded as to the type of initiator that is being constructed
* for this port.
*/
u32 status;
/**
* Virtual initiator high SAS Address
*/
u32 initiator_sas_address_hi;
/**
* Virtual initiator low SAS Address
*/
u32 initiator_sas_address_lo;
/**
* This must be 0
*/
u32 reserved;
};
/* IIT Status Defines */
#define SCU_IIT_ENTRY_ID_MASK (0xC0000000)
#define SCU_IIT_ENTRY_ID_SHIFT (30)
#define SCU_IIT_ENTRY_STATUS_UPDATE_MASK (0x20000000)
#define SCU_IIT_ENTRY_STATUS_UPDATE_SHIFT (29)
#define SCU_IIT_ENTRY_LPI_MASK (0x00000F00)
#define SCU_IIT_ENTRY_LPI_SHIFT (8)
#define SCU_IIT_ENTRY_STATUS_MASK (0x000000FF)
#define SCU_IIT_ENTRY_STATUS_SHIFT (0)
/* IIT Remote Initiator Defines */
#define SCU_IIT_ENTRY_REMOTE_TAG_MASK (0x0000FFFF)
#define SCU_IIT_ENTRY_REMOTE_TAG_SHIFT (0)
#define SCU_IIT_ENTRY_REMOTE_RNC_MASK (0x0FFF0000)
#define SCU_IIT_ENTRY_REMOTE_RNC_SHIFT (16)
#define SCU_IIT_ENTRY_ID_INVALID (0 << SCU_IIT_ENTRY_ID_SHIFT)
#define SCU_IIT_ENTRY_ID_VIIT (1 << SCU_IIT_ENTRY_ID_SHIFT)
#define SCU_IIT_ENTRY_ID_IIT (2 << SCU_IIT_ENTRY_ID_SHIFT)
#define SCU_IIT_ENTRY_ID_VIRT_EXP (3 << SCU_IIT_ENTRY_ID_SHIFT)
/**
* struct scu_iit_entry - This will be implemented later when we support
* virtual functions
*
*
*/
struct scu_iit_entry {
u32 status;
u32 remote_initiator_sas_address_hi;
u32 remote_initiator_sas_address_lo;
u32 remote_initiator;
};
#endif /* _SCU_VIIT_DATA_HEADER_ */

View File

@ -0,0 +1,491 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains isci module object implementation.
*
*
*/
#include "isci.h"
#include "request.h"
#include "sata.h"
#include "task.h"
/**
* scic_cb_stall_execution() - 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.
* @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.
*
* none.
*/
void scic_cb_stall_execution(
u32 microseconds)
{
udelay(microseconds);
}
/**
* scic_cb_io_request_get_physical_address() - This callback method asks the
* user to provide the physical address for the supplied virtual address
* when building an io request object.
* @controller: This parameter is the core controller object handle.
* @io_request: This parameter is the io request object handle for which the
* physical address is being requested.
*
*
*/
void scic_cb_io_request_get_physical_address(
struct scic_sds_controller *controller,
struct scic_sds_request *io_request,
void *virtual_address,
dma_addr_t *physical_address)
{
struct isci_request *request =
(struct isci_request *)sci_object_get_association(io_request);
char *requested_address = (char *)virtual_address;
char *base_address = (char *)request;
BUG_ON(requested_address < base_address);
BUG_ON((requested_address - base_address) >=
request->request_alloc_size);
*physical_address = request->request_daddr +
(requested_address - base_address);
}
/**
* scic_cb_io_request_get_transfer_length() - This callback method asks the
* user to provide the number of bytes to be transfered as part of this
* request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the number of payload data bytes to be transfered for
* this IO request.
*/
u32 scic_cb_io_request_get_transfer_length(
void *scic_user_io_request)
{
return isci_request_io_request_get_transfer_length(
scic_user_io_request
);
}
/**
* scic_cb_io_request_get_data_direction() - This callback method asks the user
* to provide the data direction for this request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the value of SCI_IO_REQUEST_DATA_OUT or
* SCI_IO_REQUEST_DATA_IN, or SCI_IO_REQUEST_NO_DATA.
*/
SCI_IO_REQUEST_DATA_DIRECTION scic_cb_io_request_get_data_direction(
void *scic_user_io_request)
{
return isci_request_io_request_get_data_direction(
scic_user_io_request
);
}
/**
* scic_cb_io_request_get_next_sge() - This callback method asks the user to
* provide the address to where the next Scatter-Gather Element is located.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
* @current_sge_address: This parameter specifies the address for the current
* SGE (i.e. the one that has just processed).
*
* An address specifying the location for the next scatter gather element to be
* processed.
*/
void scic_cb_io_request_get_next_sge(
void *scic_user_io_request,
void *current_sge_address,
void **next_sge)
{
*next_sge = isci_request_io_request_get_next_sge(
scic_user_io_request,
current_sge_address
);
}
/**
* scic_cb_sge_get_address_field() - This callback method asks the user to
* provide the contents of the "address" field in the Scatter-Gather Element.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
* @sge_address: This parameter specifies the address for the SGE from which to
* retrieve the address field.
*
* A physical address specifying the contents of the SGE's address field.
*/
dma_addr_t scic_cb_sge_get_address_field(
void *scic_user_io_request,
void *sge_address)
{
return isci_request_sge_get_address_field(
scic_user_io_request,
sge_address
);
}
/**
* scic_cb_sge_get_length_field() - This callback method asks the user to
* provide the contents of the "length" field in the Scatter-Gather Element.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
* @sge_address: This parameter specifies the address for the SGE from which to
* retrieve the address field.
*
* This method returns the length field specified inside the SGE referenced by
* the sge_address parameter.
*/
u32 scic_cb_sge_get_length_field(
void *scic_user_io_request,
void *sge_address)
{
return isci_request_sge_get_length_field(
scic_user_io_request,
sge_address
);
}
/**
* scic_cb_ssp_io_request_get_cdb_address() - This callback method asks the
* user to provide the address for the command descriptor block (CDB)
* associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the virtual address of the CDB.
*/
void *scic_cb_ssp_io_request_get_cdb_address(
void *scic_user_io_request)
{
return isci_request_ssp_io_request_get_cdb_address(
scic_user_io_request
);
}
/**
* scic_cb_ssp_io_request_get_cdb_length() - This callback method asks the user
* to provide the length of the command descriptor block (CDB) associated
* with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the length of the CDB.
*/
u32 scic_cb_ssp_io_request_get_cdb_length(
void *scic_user_io_request)
{
return isci_request_ssp_io_request_get_cdb_length(
scic_user_io_request
);
}
/**
* scic_cb_ssp_io_request_get_lun() - This callback method asks the user to
* provide the Logical Unit (LUN) associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the LUN associated with this request. This should be u64?
*/
u32 scic_cb_ssp_io_request_get_lun(
void *scic_user_io_request)
{
return isci_request_ssp_io_request_get_lun(scic_user_io_request);
}
/**
* scic_cb_ssp_io_request_get_task_attribute() - This callback method asks the
* user to provide the task attribute associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the task attribute associated with this IO request.
*/
u32 scic_cb_ssp_io_request_get_task_attribute(
void *scic_user_io_request)
{
return isci_request_ssp_io_request_get_task_attribute(
scic_user_io_request
);
}
/**
* scic_cb_ssp_io_request_get_command_priority() - This callback method asks
* the user to provide the command priority associated with this IO request.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the command priority associated with this IO request.
*/
u32 scic_cb_ssp_io_request_get_command_priority(
void *scic_user_io_request)
{
return isci_request_ssp_io_request_get_command_priority(
scic_user_io_request
);
}
/**
* scic_cb_ssp_task_request_get_lun() - This method returns the Logical Unit to
* be utilized for this task management request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the LUN associated with this request. This should be u64?
*/
u32 scic_cb_ssp_task_request_get_lun(
void *scic_user_task_request)
{
return isci_task_ssp_request_get_lun(
(struct isci_request *)scic_user_task_request
);
}
/**
* scic_cb_ssp_task_request_get_function() - This method returns the task
* management function to be utilized for this task request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns an unsigned byte representing the task management
* function to be performed.
*/
u8 scic_cb_ssp_task_request_get_function(
void *scic_user_task_request)
{
return isci_task_ssp_request_get_function(
(struct isci_request *)scic_user_task_request
);
}
/**
* scic_cb_ssp_task_request_get_io_tag_to_manage() - 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.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns an unsigned 16-bit word depicting the IO tag to be
* managed.
*/
u16 scic_cb_ssp_task_request_get_io_tag_to_manage(
void *scic_user_task_request)
{
return isci_task_ssp_request_get_io_tag_to_manage(
(struct isci_request *)scic_user_task_request
);
}
/**
* scic_cb_ssp_task_request_get_response_data_address() - This callback method
* asks the user to provide the virtual address of the response data buffer
* for the supplied IO request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the virtual address for the response data buffer
* associated with this IO request.
*/
void *scic_cb_ssp_task_request_get_response_data_address(
void *scic_user_task_request)
{
return isci_task_ssp_request_get_response_data_address(
(struct isci_request *)scic_user_task_request
);
}
/**
* scic_cb_ssp_task_request_get_response_data_length() - This callback method
* asks the user to provide the length of the response data buffer for the
* supplied IO request.
* @scic_user_task_request: This parameter points to the user's task request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns the length of the response buffer data associated with
* this IO request.
*/
u32 scic_cb_ssp_task_request_get_response_data_length(
void *scic_user_task_request)
{
return isci_task_ssp_request_get_response_data_length(
(struct isci_request *)scic_user_task_request
);
}
#if !defined(DISABLE_ATAPI)
/**
* scic_cb_stp_packet_io_request_get_cdb_address() - This user callback asks
* the user to provide stp packet io's the CDB address.
* @scic_user_io_request:
*
* The packet IO's cdb adress.
*/
void *scic_cb_stp_packet_io_request_get_cdb_address(
void *scic_user_io_request)
{
return isci_request_stp_packet_io_request_get_cdb_address(
scic_user_io_request
);
}
/**
* scic_cb_stp_packet_io_request_get_cdb_length() - This user callback asks the
* user to provide stp packet io's the CDB length.
* @scic_user_io_request:
*
* The packet IO's cdb length.
*/
u32 scic_cb_stp_packet_io_request_get_cdb_length(
void *scic_user_io_request)
{
return isci_request_stp_packet_io_request_get_cdb_length(
scic_user_io_request
);
}
#endif /* #if !defined(DISABLE_ATAPI) */
/**
* scic_cb_io_request_do_copy_rx_frames() - This callback method asks the user
* if the received RX frame data is to be copied to the SGL or should be
* stored by the SCI core to be retrieved later with the
* scic_io_request_get_rx_frame().
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns true if the SCI core should copy the received frame data
* to the SGL location or false if the SCI user wants to retrieve the frame
* data at a later time.
*/
bool scic_cb_io_request_do_copy_rx_frames(
void *scic_user_io_request)
{
struct sas_task *task
= isci_request_access_task(
(struct isci_request *)scic_user_io_request
);
return (task->data_dir == DMA_NONE) ? false : true;
}
/**
* scic_cb_get_virtual_address() - This callback method asks the user to
* provide the virtual address for the supplied physical address.
* @controller: This parameter is the core controller object handle.
* @physical_address: This parameter is the physical address which is to be
* returned as a virtual address.
*
* The method returns the virtual address for the supplied physical address.
*/
void *scic_cb_get_virtual_address(
struct scic_sds_controller *controller,
dma_addr_t physical_address)
{
void *virt_addr = (void *)phys_to_virt(physical_address);
return virt_addr;
}
/**
* scic_cb_request_get_sat_protocol() - This callback method asks the user to
* return the SAT protocol definition for this IO request. This method is
* only called by the SCI core if the request type constructed is SATA.
* @scic_user_io_request: This parameter points to the user's IO request
* object. It is a cookie that allows the user to provide the necessary
* information for this callback.
*
* This method returns one of the sat.h defined protocols for the given io
* request.
*/
u8 scic_cb_request_get_sat_protocol(
void *scic_user_io_request)
{
return isci_sata_get_sat_protocol(
(struct isci_request *)scic_user_io_request
);
}

619
drivers/scsi/isci/events.c Normal file
View File

@ -0,0 +1,619 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains isci module object implementation.
*
*
*/
#include "isci.h"
#include "request.h"
#include "sata.h"
#include "task.h"
/**
* scic_cb_timer_create() - This callback method asks the user to create a
* timer and provide a handle for this timer for use in further timer
* interactions. The appropriate isci timer object function is called to
* create a timer object.
* @timer_callback: This parameter specifies the callback method to be invoked
* whenever the timer expires.
* @controller: This parameter specifies the controller with which this timer
* is to be associated.
* @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.
*
* This method returns a handle to a timer object created by the user. The
* handle will be utilized for all further interactions relating to this timer.
*/
void *scic_cb_timer_create(
struct scic_sds_controller *controller,
void (*timer_callback)(void *),
void *cookie)
{
struct isci_host *isci_host;
struct isci_timer *timer = NULL;
isci_host = (struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host = %p",
__func__, isci_host);
timer = isci_timer_create(&isci_host->timer_list_struct,
isci_host,
cookie,
timer_callback);
dev_dbg(&isci_host->pdev->dev, "%s: timer = %p\n", __func__, timer);
return (void *)timer;
}
/**
* scic_cb_timer_start() - This callback method asks the user to start the
* supplied timer. The appropriate isci timer object function is called to
* start the timer.
* @controller: This parameter specifies the controller with which this timer
* is to associated.
* @timer: This parameter specifies the timer to be started.
* @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.
*
*/
void scic_cb_timer_start(
struct scic_sds_controller *controller,
void *timer,
u32 milliseconds)
{
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host = %p, timer = %p, milliseconds = %d\n",
__func__, isci_host, timer, milliseconds);
isci_timer_start((struct isci_timer *)timer, milliseconds);
}
/**
* scic_cb_timer_stop() - This callback method asks the user to stop the
* supplied timer. The appropriate isci timer object function is called to
* stop the timer.
* @controller: This parameter specifies the controller with which this timer
* is to associated.
* @timer: This parameter specifies the timer to be stopped.
*
*/
void scic_cb_timer_stop(
struct scic_sds_controller *controller,
void *timer)
{
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host = %p, timer = %p\n",
__func__, isci_host, timer);
isci_timer_stop((struct isci_timer *)timer);
}
/**
* scic_cb_controller_start_complete() - This user callback will inform the
* user that the controller has finished the start process. The associated
* isci host adapter's start_complete function is called.
* @controller: This parameter specifies the controller that was started.
* @completion_status: This parameter specifies the results of the start
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_controller_start_complete(
struct scic_sds_controller *controller,
enum sci_status completion_status)
{
struct isci_host *isci_host =
(struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host = %p\n", __func__, isci_host);
isci_host_start_complete(isci_host, completion_status);
}
/**
* scic_cb_controller_stop_complete() - This user callback will inform the user
* that the controller has finished the stop process. The associated isci
* host adapter's start_complete function is called.
* @controller: This parameter specifies the controller that was stopped.
* @completion_status: This parameter specifies the results of the stop
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_controller_stop_complete(
struct scic_sds_controller *controller,
enum sci_status completion_status)
{
struct isci_host *isci_host =
(struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: status = 0x%x\n", __func__, completion_status);
isci_host_stop_complete(isci_host, completion_status);
}
/**
* scic_cb_io_request_complete() - This user callback will inform the user that
* an IO request has completed.
* @controller: This parameter specifies the controller on which the IO is
* completing.
* @remote_device: This parameter specifies the remote device on which this IO
* request is completing.
* @io_request: This parameter specifies the IO request that has completed.
* @completion_status: This parameter specifies the results of the IO request
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_io_request_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *scic_io_request,
enum sci_io_status completion_status)
{
struct isci_request *request;
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
request =
(struct isci_request *)sci_object_get_association(
scic_io_request
);
isci_request_io_request_complete(isci_host,
request,
completion_status);
}
/**
* scic_cb_task_request_complete() - This user callback will inform the user
* that a task management request completed.
* @controller: This parameter specifies the controller on which the task
* management request is completing.
* @remote_device: This parameter specifies the remote device on which this
* task management request is completing.
* @task_request: This parameter specifies the task management request that has
* completed.
* @completion_status: This parameter specifies the results of the IO request
* operation. SCI_SUCCESS indicates successful completion.
*
*/
void scic_cb_task_request_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
struct scic_sds_request *scic_task_request,
enum sci_task_status completion_status)
{
struct isci_request *request;
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
request =
(struct isci_request *)sci_object_get_association(
scic_task_request);
isci_task_request_complete(isci_host, request, completion_status);
}
/**
* scic_cb_port_stop_complete() - This method informs the user when a stop
* operation on the port has completed.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
* @completion_status: This parameter specifies the status for the operation
* being completed.
*
*/
void scic_cb_port_stop_complete(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
enum sci_status completion_status)
{
pr_warn("%s:************************************************\n",
__func__);
}
/**
* scic_cb_port_hard_reset_complete() - This method informs the user when a
* hard reset on the port has completed. This hard reset could have been
* initiated by the user or by the remote port.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
* @completion_status: This parameter specifies the status for the operation
* being completed.
*
*/
void scic_cb_port_hard_reset_complete(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
enum sci_status completion_status)
{
struct isci_port *isci_port
= (struct isci_port *)sci_object_get_association(port);
isci_port_hard_reset_complete(isci_port, completion_status);
}
/**
* scic_cb_port_ready() - This method informs the user that the port is now in
* a ready state and can be utilized to issue IOs.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
*
*/
void scic_cb_port_ready(
struct scic_sds_controller *controller,
struct scic_sds_port *port)
{
struct isci_port *isci_port;
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
isci_port =
(struct isci_port *)sci_object_get_association(port);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p\n", __func__, isci_port);
isci_port_ready(isci_host, isci_port);
}
/**
* scic_cb_port_not_ready() - This method informs the user that the port is now
* not in a ready (i.e. busy) state and can't be utilized to issue IOs.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
*
*/
void scic_cb_port_not_ready(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
u32 reason_code)
{
struct isci_port *isci_port;
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
isci_port =
(struct isci_port *)sci_object_get_association(port);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p\n", __func__, isci_port);
isci_port_not_ready(isci_host, isci_port);
}
/**
* scic_cb_port_invalid_link_up() - 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.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked.
* @phy: This parameter specifies the phy that came ready, but the phy can't be
* a valid member of the port.
*
*/
void scic_cb_port_invalid_link_up(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
pr_warn("%s:************************************************\n",
__func__);
}
/**
* scic_cb_port_bc_change_primitive_received() - This callback method informs
* the user that a broadcast change primitive was received.
* @controller: This parameter represents the controller which contains the
* port.
* @port: This parameter specifies the SCI port object for which the callback
* is being invoked. For instances where the phy on which the primitive was
* received is not part of a port, this parameter will be
* SCI_INVALID_HANDLE_T.
* @phy: This parameter specifies the phy on which the primitive was received.
*
*/
void scic_cb_port_bc_change_primitive_received(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: port = %p, phy = %p\n", __func__, port, phy);
isci_port_bc_change_received(isci_host, port, phy);
}
/**
* scic_cb_port_link_up() - This callback method informs the user that a phy
* has become operational and is capable of communicating with the remote
* end point.
* @controller: This parameter represents the controller associated with the
* phy.
* @port: This parameter specifies the port object for which the user callback
* is being invoked. There may be conditions where this parameter can be
* SCI_INVALID_HANDLE
* @phy: This parameter specifies the phy object for which the user callback is
* being invoked.
*
* none.
*/
void scic_cb_port_link_up(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: phy = %p\n", __func__, phy);
isci_port_link_up(isci_host, port, phy);
}
/**
* scic_cb_port_link_down() - This callback method informs the user that a phy
* is no longer operational and is not capable of communicating with the
* remote end point.
* @controller: This parameter represents the controller associated with the
* phy.
* @port: This parameter specifies the port object for which the user callback
* is being invoked. There may be conditions where this parameter can be
* SCI_INVALID_HANDLE
* @phy: This parameter specifies the phy object for which the user callback is
* being invoked.
*
* none.
*/
void scic_cb_port_link_down(
struct scic_sds_controller *controller,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
struct isci_host *isci_host;
struct isci_phy *isci_phy;
struct isci_port *isci_port;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
isci_phy =
(struct isci_phy *)sci_object_get_association(phy);
isci_port =
(struct isci_port *)sci_object_get_association(port);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p\n", __func__, isci_port);
isci_port_link_down(isci_host, isci_phy, isci_port);
}
/**
* scic_cb_remote_device_start_complete() - This user callback method will
* inform the user that a start operation has completed.
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the completion callback.
* @completion_status: This parameter specifies the completion status for the
* operation.
*
*/
void scic_cb_remote_device_start_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
enum sci_status completion_status)
{
struct isci_host *isci_host;
struct isci_remote_device *isci_device;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
isci_device =
(struct isci_remote_device *)sci_object_get_association(
remote_device
);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
isci_remote_device_start_complete(
isci_host, isci_device, completion_status);
}
/**
* scic_cb_remote_device_stop_complete() - This user callback method will
* inform the user that a stop operation has completed.
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the completion callback.
* @completion_status: This parameter specifies the completion status for the
* operation.
*
*/
void scic_cb_remote_device_stop_complete(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
enum sci_status completion_status)
{
struct isci_host *isci_host;
struct isci_remote_device *isci_device;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
isci_device =
(struct isci_remote_device *)sci_object_get_association(
remote_device
);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
isci_remote_device_stop_complete(
isci_host, isci_device, completion_status);
}
/**
* scic_cb_remote_device_ready() - This user callback method will inform the
* user that a remote device is now capable of handling IO requests.
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the callback.
*
*/
void scic_cb_remote_device_ready(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device)
{
struct isci_remote_device *isci_device =
(struct isci_remote_device *)
sci_object_get_association(remote_device);
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
isci_remote_device_ready(isci_device);
}
/**
* scic_cb_remote_device_not_ready() - This user callback method will inform
* the user that a remote device is no longer capable of handling IO
* requests (until a ready callback is invoked).
* @controller: This parameter specifies the core controller associated with
* the completion callback.
* @remote_device: This parameter specifies the remote device associated with
* the callback.
* @reason_code: This parameter specifies the reason for the remote device
* going to a not ready state.
*
*/
void scic_cb_remote_device_not_ready(
struct scic_sds_controller *controller,
struct scic_sds_remote_device *remote_device,
u32 reason_code)
{
struct isci_remote_device *isci_device =
(struct isci_remote_device *)
sci_object_get_association(remote_device);
struct isci_host *isci_host;
isci_host =
(struct isci_host *)sci_object_get_association(controller);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p, reason_code = %x\n",
__func__, isci_device, reason_code);
isci_remote_device_not_ready(isci_device, reason_code);
}

View File

@ -0,0 +1,19 @@
# Makefile for create_fw
#
CC=gcc
CFLAGS=-c -Wall -O2 -g
LDFLAGS=
SOURCES=create_fw.c
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=create_fw
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
.c.o:
$(CC) $(CFLAGS) $< -O $@
clean:
rm -f *.o $(EXECUTABLE)

View File

@ -0,0 +1,36 @@
This defines the temporary binary blow we are to pass to the SCU
driver to emulate the binary firmware that we will eventually be
able to access via NVRAM on the SCU controller.
The current size of the binary blob is expected to be 149 bytes or larger
Header Types:
0x1: Phy Masks
0x2: Phy Gens
0x3: SAS Addrs
0xff: End of Data
ID string - u8[12]: "#SCU MAGIC#\0"
Version - u8: 1
SubVersion - u8: 0
Header Type - u8: 0x1
Size - u8: 8
Phy Mask - u32[8]
Header Type - u8: 0x2
Size - u8: 8
Phy Gen - u32[8]
Header Type - u8: 0x3
Size - u8: 8
Sas Addr - u64[8]
Header Type - u8: 0xf
==============================================================================
Place isci_firmware.bin in /lib/firmware
Be sure to recreate the initramfs image to include the firmware.

View File

@ -0,0 +1,177 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
char blob_name[] = "isci_firmware.bin";
char id[] = "#SCU MAGIC#";
unsigned char version = 1;
unsigned char sub_version = 0;
/*
* For all defined arrays:
* elements 0-3 are for SCU0, ports 0-3
* elements 4-7 are for SCU1, ports 0-3
*
* valid configurations for one SCU are:
* P0 P1 P2 P3
* ----------------
* 0xF,0x0,0x0,0x0 # 1 x4 port
* 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
* # ports
* 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
* # port
* 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
* 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
*
* if there is a port/phy on which you do not wish to override the default
* values, use the value assigned to UNINIT_PARAM (255).
*/
unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 };
/* denotes SAS generation. i.e. 3: SAS Gen 3 6G */
unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 };
/*
* if there is a port/phy on which you do not wish to override the default
* values, use the value "0000000000000000". SAS address of zero's is
* considered invalid and will not be used.
*/
unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL,
0x5FCFFFFFF1000000ULL,
0x5FCFFFFFF2000000ULL,
0x5FCFFFFFF3000000ULL,
0x5FCFFFFFF4000000ULL,
0x5FCFFFFFF5000000ULL,
0x5FCFFFFFF6000000ULL,
0x5FCFFFFFF7000000ULL };
int write_blob(void)
{
FILE *fd;
int err;
fd = fopen(blob_name, "w+");
if (!fd) {
perror("Open file for write failed");
return -EIO;
}
/* write id */
err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd);
if (err == 0) {
perror("write id failed");
return err;
}
/* write version */
err = fwrite((void *)&version, sizeof(version), 1, fd);
if (err == 0) {
perror("write version failed");
return err;
}
/* write sub version */
err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd);
if (err == 0) {
perror("write subversion failed");
return err;
}
/* write phy mask header */
err = fputc(0x1, fd);
if (err == EOF) {
perror("write phy mask header failed");
return -EIO;
}
/* write size */
err = fputc(8, fd);
if (err == EOF) {
perror("write phy mask size failed");
return -EIO;
}
/* write phy masks */
err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd);
if (err == 0) {
perror("write phy_mask failed");
return err;
}
/* write phy gen header */
err = fputc(0x2, fd);
if (err == EOF) {
perror("write phy gen header failed");
return -EIO;
}
/* write size */
err = fputc(8, fd);
if (err == EOF) {
perror("write phy gen size failed");
return -EIO;
}
/* write phy_gen */
err = fwrite((void *)phy_gen,
1,
sizeof(phy_gen),
fd);
if (err == 0) {
perror("write phy_gen failed");
return err;
}
/* write phy gen header */
err = fputc(0x3, fd);
if (err == EOF) {
perror("write sas addr header failed");
return -EIO;
}
/* write size */
err = fputc(8, fd);
if (err == EOF) {
perror("write sas addr size failed");
return -EIO;
}
/* write sas_addr */
err = fwrite((void *)sas_addr,
1,
sizeof(sas_addr),
fd);
if (err == 0) {
perror("write sas_addr failed");
return err;
}
/* write end header */
err = fputc(0xff, fd);
if (err == EOF) {
perror("write end header failed");
return -EIO;
}
fclose(fd);
return 0;
}
int main(void)
{
int err;
err = write_blob();
if (err < 0)
return err;
return 0;
}

781
drivers/scsi/isci/host.c Normal file
View File

@ -0,0 +1,781 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "isci.h"
#include "scic_io_request.h"
#include "scic_remote_device.h"
#include "scic_port.h"
#include "port.h"
#include "request.h"
#include "host.h"
/**
* isci_isr() - This function is the interrupt service routine for the
* controller. It schedules the tasklet and returns.
* @vec: This parameter specifies the interrupt vector.
* @data: This parameter specifies the ISCI host object.
*
* IRQ_HANDLED if out interrupt otherwise, IRQ_NONE
*/
irqreturn_t isci_isr(int vec, void *data)
{
struct isci_host *isci_host
= (struct isci_host *)data;
struct scic_controller_handler_methods *handlers
= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
irqreturn_t ret = IRQ_NONE;
if (isci_host_get_state(isci_host) != isci_starting
&& handlers->interrupt_handler) {
if (handlers->interrupt_handler(isci_host->core_controller)) {
if (isci_host_get_state(isci_host) != isci_stopped) {
tasklet_schedule(
&isci_host->completion_tasklet);
} else
dev_dbg(&isci_host->pdev->dev,
"%s: controller stopped\n",
__func__);
ret = IRQ_HANDLED;
}
} else
dev_warn(&isci_host->pdev->dev,
"%s: get_handler_methods failed, "
"isci_host->status = 0x%x\n",
__func__,
isci_host_get_state(isci_host));
return ret;
}
irqreturn_t isci_legacy_isr(int vec, void *data)
{
struct pci_dev *pdev = data;
struct isci_host *isci_host;
struct scic_controller_handler_methods *handlers;
irqreturn_t ret = IRQ_NONE;
/*
* Since this is a legacy interrupt, either or both
* controllers could have triggered it. Thus, we have to call
* the legacy interrupt handler for all controllers on the
* PCI function.
*/
for_each_isci_host(isci_host, pdev) {
handlers = &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
if (isci_host_get_state(isci_host) != isci_starting
&& handlers->interrupt_handler) {
if (handlers->interrupt_handler(isci_host->core_controller)) {
if (isci_host_get_state(isci_host) != isci_stopped) {
tasklet_schedule(
&isci_host->completion_tasklet);
} else
dev_dbg(&isci_host->pdev->dev,
"%s: controller stopped\n",
__func__);
ret = IRQ_HANDLED;
}
} else
dev_warn(&isci_host->pdev->dev,
"%s: get_handler_methods failed, "
"isci_host->status = 0x%x\n",
__func__,
isci_host_get_state(isci_host));
}
return ret;
}
/**
* isci_host_start_complete() - This function is called by the core library,
* through the ISCI Module, to indicate controller start status.
* @isci_host: This parameter specifies the ISCI host object
* @completion_status: This parameter specifies the completion status from the
* core library.
*
*/
void isci_host_start_complete(
struct isci_host *isci_host,
enum sci_status completion_status)
{
if (completion_status == SCI_SUCCESS) {
dev_dbg(&isci_host->pdev->dev,
"%s: completion_status: SCI_SUCCESS\n", __func__);
isci_host_change_state(isci_host, isci_ready);
complete_all(&isci_host->start_complete);
} else
dev_err(&isci_host->pdev->dev,
"controller start failed with "
"completion_status = 0x%x;",
completion_status);
}
/**
* isci_host_scan_finished() - This function is one of the SCSI Host Template
* functions. The SCSI midlayer calls this function during a target scan,
* approx. once every 10 millisecs.
* @shost: This parameter specifies the SCSI host being scanned
* @time: This parameter specifies the number of ticks since the scan started.
*
* scan status, zero indicates the SCSI midlayer should continue to poll,
* otherwise assume controller is ready.
*/
int isci_host_scan_finished(
struct Scsi_Host *shost,
unsigned long time)
{
struct isci_host *isci_host
= isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost));
struct scic_controller_handler_methods *handlers
= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
if (handlers->interrupt_handler == NULL) {
dev_err(&isci_host->pdev->dev,
"%s: scic_controller_get_handler_methods failed\n",
__func__);
return 1;
}
/**
* check interrupt_handler's status and call completion_handler if true,
* link_up events should be coming from the scu core lib, as phy's come
* online. for each link_up from the core, call
* get_received_identify_address_frame, copy the frame into the
* sas_phy object and call libsas notify_port_event(PORTE_BYTES_DMAED).
* continue to return zero from thee scan_finished routine until
* the scic_cb_controller_start_complete() call comes from the core.
**/
if (handlers->interrupt_handler(isci_host->core_controller))
handlers->completion_handler(isci_host->core_controller);
if (isci_starting == isci_host_get_state(isci_host)
&& time < (HZ * 10)) {
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host->status = %d, time = %ld\n",
__func__, isci_host_get_state(isci_host), time);
return 0;
}
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host->status = %d, time = %ld\n",
__func__, isci_host_get_state(isci_host), time);
scic_controller_enable_interrupts(isci_host->core_controller);
return 1;
}
/**
* isci_host_scan_start() - This function is one of the SCSI Host Template
* function, called by the SCSI mid layer berfore a target scan begins. The
* core library controller start routine is called from here.
* @shost: This parameter specifies the SCSI host to be scanned
*
*/
void isci_host_scan_start(struct Scsi_Host *shost)
{
struct isci_host *isci_host;
isci_host = isci_host_from_sas_ha(SHOST_TO_SAS_HA(shost));
isci_host_change_state(isci_host, isci_starting);
scic_controller_disable_interrupts(isci_host->core_controller);
init_completion(&isci_host->start_complete);
scic_controller_start(
isci_host->core_controller,
scic_controller_get_suggested_start_timeout(
isci_host->core_controller)
);
}
void isci_host_stop_complete(
struct isci_host *isci_host,
enum sci_status completion_status)
{
isci_host_change_state(isci_host, isci_stopped);
scic_controller_disable_interrupts(
isci_host->core_controller
);
complete(&isci_host->stop_complete);
}
static struct coherent_memory_info *isci_host_alloc_mdl_struct(
struct isci_host *isci_host,
u32 size)
{
struct coherent_memory_info *mdl_struct;
void *uncached_address = NULL;
mdl_struct = devm_kzalloc(&isci_host->pdev->dev,
sizeof(*mdl_struct),
GFP_KERNEL);
if (!mdl_struct)
return NULL;
INIT_LIST_HEAD(&mdl_struct->node);
uncached_address = dmam_alloc_coherent(&isci_host->pdev->dev,
size,
&mdl_struct->dma_handle,
GFP_KERNEL);
if (!uncached_address)
return NULL;
/* memset the whole memory area. */
memset((char *)uncached_address, 0, size);
mdl_struct->vaddr = uncached_address;
mdl_struct->size = (size_t)size;
return mdl_struct;
}
static void isci_host_build_mde(
struct sci_physical_memory_descriptor *mde_struct,
struct coherent_memory_info *mdl_struct)
{
unsigned long address = 0;
dma_addr_t dma_addr = 0;
address = (unsigned long)mdl_struct->vaddr;
dma_addr = mdl_struct->dma_handle;
/* to satisfy the alignment. */
if ((address % mde_struct->constant_memory_alignment) != 0) {
int align_offset
= (mde_struct->constant_memory_alignment
- (address % mde_struct->constant_memory_alignment));
address += align_offset;
dma_addr += align_offset;
}
mde_struct->virtual_address = (void *)address;
mde_struct->physical_address = dma_addr;
mdl_struct->mde = mde_struct;
}
static int isci_host_mdl_allocate_coherent(
struct isci_host *isci_host)
{
struct sci_physical_memory_descriptor *current_mde;
struct coherent_memory_info *mdl_struct;
u32 size = 0;
struct sci_base_memory_descriptor_list *mdl_handle
= sci_controller_get_memory_descriptor_list_handle(
isci_host->core_controller);
sci_mdl_first_entry(mdl_handle);
current_mde = sci_mdl_get_current_entry(mdl_handle);
while (current_mde != NULL) {
size = (current_mde->constant_memory_size
+ current_mde->constant_memory_alignment);
mdl_struct = isci_host_alloc_mdl_struct(isci_host, size);
if (!mdl_struct)
return -ENOMEM;
list_add_tail(&mdl_struct->node, &isci_host->mdl_struct_list);
isci_host_build_mde(current_mde, mdl_struct);
sci_mdl_next_entry(mdl_handle);
current_mde = sci_mdl_get_current_entry(mdl_handle);
}
return 0;
}
/**
* isci_host_completion_routine() - This function is the delayed service
* routine that calls the sci core library's completion handler. It's
* scheduled as a tasklet from the interrupt service routine when interrupts
* in use, or set as the timeout function in polled mode.
* @data: This parameter specifies the ISCI host object
*
*/
static void isci_host_completion_routine(unsigned long data)
{
struct isci_host *isci_host = (struct isci_host *)data;
struct scic_controller_handler_methods *handlers
= &isci_host->scic_irq_handlers[SCI_MSIX_NORMAL_VECTOR];
struct list_head completed_request_list;
struct list_head aborted_request_list;
struct list_head *current_position;
struct list_head *next_position;
struct isci_request *request;
struct isci_request *next_request;
struct sas_task *task;
INIT_LIST_HEAD(&completed_request_list);
INIT_LIST_HEAD(&aborted_request_list);
spin_lock_irq(&isci_host->scic_lock);
if (handlers->completion_handler) {
handlers->completion_handler(
isci_host->core_controller
);
}
/* Take the lists of completed I/Os from the host. */
list_splice_init(&isci_host->requests_to_complete,
&completed_request_list);
list_splice_init(&isci_host->requests_to_abort,
&aborted_request_list);
spin_unlock_irq(&isci_host->scic_lock);
/* Process any completions in the lists. */
list_for_each_safe(current_position, next_position,
&completed_request_list) {
request = list_entry(current_position, struct isci_request,
completed_node);
task = isci_request_access_task(request);
/* Normal notification (task_done) */
dev_dbg(&isci_host->pdev->dev,
"%s: Normal - request/task = %p/%p\n",
__func__,
request,
task);
task->task_done(task);
task->lldd_task = NULL;
/* Free the request object. */
isci_request_free(isci_host, request);
}
list_for_each_entry_safe(request, next_request, &aborted_request_list,
completed_node) {
task = isci_request_access_task(request);
/* Use sas_task_abort */
dev_warn(&isci_host->pdev->dev,
"%s: Error - request/task = %p/%p\n",
__func__,
request,
task);
/* Put the task into the abort path. */
sas_task_abort(task);
}
}
void isci_host_deinit(
struct isci_host *isci_host)
{
int i;
isci_host_change_state(isci_host, isci_stopping);
for (i = 0; i < SCI_MAX_PORTS; i++) {
struct isci_port *port = &isci_host->isci_ports[i];
struct isci_remote_device *device, *tmpdev;
list_for_each_entry_safe(device, tmpdev,
&port->remote_dev_list, node) {
isci_remote_device_change_state(device, isci_stopping);
isci_remote_device_stop(device);
}
}
/* stop the comtroller and wait for completion. */
init_completion(&isci_host->stop_complete);
scic_controller_stop(
isci_host->core_controller,
SCIC_CONTROLLER_STOP_TIMEOUT
);
wait_for_completion(&isci_host->stop_complete);
/* next, reset the controller. */
scic_controller_reset(isci_host->core_controller);
}
static int isci_verify_firmware(const struct firmware *fw,
struct isci_firmware *isci_fw)
{
const u8 *tmp;
if (fw->size < ISCI_FIRMWARE_MIN_SIZE)
return -EINVAL;
tmp = fw->data;
/* 12th char should be the NULL terminate for the ID string */
if (tmp[11] != '\0')
return -EINVAL;
if (strncmp("#SCU MAGIC#", tmp, 11) != 0)
return -EINVAL;
isci_fw->id = tmp;
isci_fw->version = fw->data[ISCI_FW_VER_OFS];
isci_fw->subversion = fw->data[ISCI_FW_SUBVER_OFS];
tmp = fw->data + ISCI_FW_DATA_OFS;
while (*tmp != ISCI_FW_HDR_EOF) {
switch (*tmp) {
case ISCI_FW_HDR_PHYMASK:
tmp++;
isci_fw->phy_masks_size = *tmp;
tmp++;
isci_fw->phy_masks = (const u32 *)tmp;
tmp += sizeof(u32) * isci_fw->phy_masks_size;
break;
case ISCI_FW_HDR_PHYGEN:
tmp++;
isci_fw->phy_gens_size = *tmp;
tmp++;
isci_fw->phy_gens = (const u32 *)tmp;
tmp += sizeof(u32) * isci_fw->phy_gens_size;
break;
case ISCI_FW_HDR_SASADDR:
tmp++;
isci_fw->sas_addrs_size = *tmp;
tmp++;
isci_fw->sas_addrs = (const u64 *)tmp;
tmp += sizeof(u64) * isci_fw->sas_addrs_size;
break;
default:
pr_err("bad field in firmware binary blob\n");
return -EINVAL;
}
}
pr_info("isci firmware v%u.%u loaded.\n",
isci_fw->version, isci_fw->subversion);
return SCI_SUCCESS;
}
static void __iomem *scu_base(struct isci_host *isci_host)
{
struct pci_dev *pdev = isci_host->pdev;
int id = isci_host->id;
return pcim_iomap_table(pdev)[SCI_SCU_BAR * 2] + SCI_SCU_BAR_SIZE * id;
}
static void __iomem *smu_base(struct isci_host *isci_host)
{
struct pci_dev *pdev = isci_host->pdev;
int id = isci_host->id;
return pcim_iomap_table(pdev)[SCI_SMU_BAR * 2] + SCI_SMU_BAR_SIZE * id;
}
#define SCI_MAX_TIMER_COUNT 25
int isci_host_init(struct isci_host *isci_host)
{
int err = 0;
int index = 0;
enum sci_status status;
struct scic_sds_controller *controller;
struct scic_sds_port *scic_port;
struct scic_controller_handler_methods *handlers
= &isci_host->scic_irq_handlers[0];
union scic_oem_parameters scic_oem_params;
union scic_user_parameters scic_user_params;
const struct firmware *fw = NULL;
struct isci_firmware *isci_fw = NULL;
INIT_LIST_HEAD(&isci_host->timer_list_struct.timers);
isci_timer_list_construct(
&isci_host->timer_list_struct,
SCI_MAX_TIMER_COUNT
);
controller = scic_controller_alloc(&isci_host->pdev->dev);
if (!controller) {
err = -ENOMEM;
dev_err(&isci_host->pdev->dev, "%s: failed (%d)\n", __func__, err);
goto out;
}
isci_host->core_controller = controller;
spin_lock_init(&isci_host->state_lock);
spin_lock_init(&isci_host->scic_lock);
spin_lock_init(&isci_host->queue_lock);
isci_host_change_state(isci_host, isci_starting);
isci_host->can_queue = ISCI_CAN_QUEUE_VAL;
status = scic_controller_construct(controller, scu_base(isci_host),
smu_base(isci_host));
if (status != SCI_SUCCESS) {
dev_err(&isci_host->pdev->dev,
"%s: scic_controller_construct failed - status = %x\n",
__func__,
status);
err = -ENODEV;
goto out;
}
isci_host->sas_ha.dev = &isci_host->pdev->dev;
isci_host->sas_ha.lldd_ha = isci_host;
/*----------- SCIC controller Initialization Stuff ------------------
* set association host adapter struct in core controller.
*/
sci_object_set_association(isci_host->core_controller,
(void *)isci_host
);
/* grab initial values stored in the controller object for OEM and USER
* parameters */
scic_oem_parameters_get(controller, &scic_oem_params);
scic_user_parameters_get(controller, &scic_user_params);
isci_fw = devm_kzalloc(&isci_host->pdev->dev,
sizeof(struct isci_firmware),
GFP_KERNEL);
if (!isci_fw) {
dev_warn(&isci_host->pdev->dev,
"allocating firmware struct failed\n");
dev_warn(&isci_host->pdev->dev,
"Default OEM configuration being used:"
" 4 narrow ports, and default SAS Addresses\n");
goto set_default_params;
}
status = request_firmware(&fw, ISCI_FW_NAME, &isci_host->pdev->dev);
if (status) {
dev_warn(&isci_host->pdev->dev,
"Loading firmware failed, using default values\n");
dev_warn(&isci_host->pdev->dev,
"Default OEM configuration being used:"
" 4 narrow ports, and default SAS Addresses\n");
goto set_default_params;
}
else {
status = isci_verify_firmware(fw, isci_fw);
if (status != SCI_SUCCESS) {
dev_warn(&isci_host->pdev->dev,
"firmware verification failed\n");
dev_warn(&isci_host->pdev->dev,
"Default OEM configuration being used:"
" 4 narrow ports, and default SAS "
"Addresses\n");
goto set_default_params;
}
/* grab any OEM and USER parameters specified at module load */
status = isci_parse_oem_parameters(&scic_oem_params,
isci_host->id, isci_fw);
if (status != SCI_SUCCESS) {
dev_warn(&isci_host->pdev->dev,
"parsing firmware oem parameters failed\n");
err = -EINVAL;
goto out;
}
status = isci_parse_user_parameters(&scic_user_params,
isci_host->id, isci_fw);
if (status != SCI_SUCCESS) {
dev_warn(&isci_host->pdev->dev,
"%s: isci_parse_user_parameters"
" failed\n", __func__);
err = -EINVAL;
goto out;
}
}
set_default_params:
status = scic_oem_parameters_set(isci_host->core_controller,
&scic_oem_params
);
if (status != SCI_SUCCESS) {
dev_warn(&isci_host->pdev->dev,
"%s: scic_oem_parameters_set failed\n",
__func__);
err = -ENODEV;
goto out;
}
status = scic_user_parameters_set(isci_host->core_controller,
&scic_user_params
);
if (status != SCI_SUCCESS) {
dev_warn(&isci_host->pdev->dev,
"%s: scic_user_parameters_set failed\n",
__func__);
err = -ENODEV;
goto out;
}
status = scic_controller_initialize(isci_host->core_controller);
if (status != SCI_SUCCESS) {
dev_warn(&isci_host->pdev->dev,
"%s: scic_controller_initialize failed -"
" status = 0x%x\n",
__func__, status);
err = -ENODEV;
goto out;
}
/* @todo: use both MSI-X interrupts, and don't do indirect
* calls to the handlers just register direct calls
*/
if (isci_host->pdev->msix_enabled) {
status = scic_controller_get_handler_methods(
SCIC_MSIX_INTERRUPT_TYPE,
SCI_MSIX_DOUBLE_VECTOR,
handlers
);
} else {
status = scic_controller_get_handler_methods(
SCIC_LEGACY_LINE_INTERRUPT_TYPE,
0,
handlers
);
}
if (status != SCI_SUCCESS) {
handlers->interrupt_handler = NULL;
handlers->completion_handler = NULL;
dev_err(&isci_host->pdev->dev,
"%s: scic_controller_get_handler_methods failed\n",
__func__);
}
tasklet_init(&isci_host->completion_tasklet,
isci_host_completion_routine,
(unsigned long)isci_host
);
INIT_LIST_HEAD(&(isci_host->mdl_struct_list));
INIT_LIST_HEAD(&isci_host->requests_to_complete);
INIT_LIST_HEAD(&isci_host->requests_to_abort);
/* populate mdl with dma memory. scu_mdl_allocate_coherent() */
err = isci_host_mdl_allocate_coherent(isci_host);
if (err)
goto err_out;
/*
* keep the pool alloc size around, will use it for a bounds checking
* when trying to convert virtual addresses to physical addresses
*/
isci_host->dma_pool_alloc_size = sizeof(struct isci_request) +
scic_io_request_get_object_size();
isci_host->dma_pool = dmam_pool_create(DRV_NAME, &isci_host->pdev->dev,
isci_host->dma_pool_alloc_size,
SLAB_HWCACHE_ALIGN, 0);
if (!isci_host->dma_pool) {
err = -ENOMEM;
goto req_obj_err_out;
}
for (index = 0; index < SCI_MAX_PORTS; index++) {
isci_port_init(&isci_host->isci_ports[index],
isci_host, index);
}
for (index = 0; index < SCI_MAX_PHYS; index++)
isci_phy_init(&isci_host->phys[index], isci_host, index);
/* Why are we doing this? Is this even necessary? */
memcpy(&isci_host->sas_addr[0], &isci_host->phys[0].sas_addr[0],
SAS_ADDR_SIZE);
/* Start the ports */
for (index = 0; index < SCI_MAX_PORTS; index++) {
scic_controller_get_port_handle(controller, index, &scic_port);
scic_port_start(scic_port);
}
goto out;
/* SPB_Debug: destroy request object cache */
req_obj_err_out:
/* SPB_Debug: destroy remote object cache */
err_out:
/* SPB_Debug: undo controller init, construct and alloc, remove from parent
* controller list. */
out:
if (fw)
release_firmware(fw);
return err;
}

283
drivers/scsi/isci/host.h Normal file
View File

@ -0,0 +1,283 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the isci_module initialization routines.
*
* host.h
*/
#if !defined(_SCI_HOST_H_)
#define _SCI_HOST_H_
#include "phy.h"
/*#include "task.h"*/
#include "timers.h"
#include "remote_device.h"
#include "scic_user_callback.h"
#define DRV_NAME "isci"
#define SCI_PCI_BAR_COUNT 2
#define SCI_NUM_MSI_X_INT 2
#define SCI_SMU_BAR 0
#define SCI_SMU_BAR_SIZE (16*1024)
#define SCI_SCU_BAR 1
#define SCI_SCU_BAR_SIZE (4*1024*1024)
#define SCI_IO_SPACE_BAR0 2
#define SCI_IO_SPACE_BAR1 3
#define SCI_MSIX_NORMAL_VECTOR 0
#define SCI_MSIX_ERROR_VECTOR 1
#define SCI_MSIX_SINGLE_VECTOR 1
#define SCI_MSIX_DOUBLE_VECTOR 2
#define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */
#define SCIC_CONTROLLER_STOP_TIMEOUT 5000
struct coherent_memory_info {
struct list_head node;
dma_addr_t dma_handle;
void *vaddr;
size_t size;
struct sci_physical_memory_descriptor *mde;
};
struct isci_host {
struct scic_sds_controller *core_controller;
struct scic_controller_handler_methods scic_irq_handlers[SCI_NUM_MSI_X_INT];
union scic_oem_parameters oem_parameters;
int id; /* unique within a given pci device */
struct isci_timer_list timer_list_struct;
void *core_ctrl_memory;
struct dma_pool *dma_pool;
unsigned int dma_pool_alloc_size;
struct isci_phy phys[SCI_MAX_PHYS];
/* isci_ports and sas_ports are implicitly parallel to the
* ports maintained by the core
*/
struct isci_port isci_ports[SCI_MAX_PORTS];
struct asd_sas_port sas_ports[SCI_MAX_PORTS];
struct sas_ha_struct sas_ha;
int can_queue;
spinlock_t queue_lock;
spinlock_t state_lock;
struct pci_dev *pdev;
u8 sas_addr[SAS_ADDR_SIZE];
enum isci_status status;
struct Scsi_Host *shost;
struct tasklet_struct completion_tasklet;
struct list_head mdl_struct_list;
struct list_head requests_to_complete;
struct list_head requests_to_abort;
struct completion stop_complete;
struct completion start_complete;
spinlock_t scic_lock;
struct isci_host *next;
};
/**
* struct isci_pci_info - This class represents the pci function containing the
* controllers. Depending on PCI SKU, there could be up to 2 controllers in
* the PCI function.
*/
#define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
struct isci_pci_info {
struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
int core_lib_array_index;
SCI_LIBRARY_HANDLE_T core_lib_handle;
struct isci_host *hosts;
};
static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
{
return pci_get_drvdata(pdev);
}
#define for_each_isci_host(isci_host, pdev) \
for (isci_host = to_pci_info(pdev)->hosts;\
isci_host; isci_host = isci_host->next)
static inline
enum isci_status isci_host_get_state(
struct isci_host *isci_host)
{
return isci_host->status;
}
static inline void isci_host_change_state(
struct isci_host *isci_host,
enum isci_status status)
{
unsigned long flags;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host = %p, state = 0x%x",
__func__,
isci_host,
status);
spin_lock_irqsave(&isci_host->state_lock, flags);
isci_host->status = status;
spin_unlock_irqrestore(&isci_host->state_lock, flags);
}
static inline int isci_host_can_queue(
struct isci_host *isci_host,
int num)
{
int ret = 0;
unsigned long flags;
spin_lock_irqsave(&isci_host->queue_lock, flags);
if ((isci_host->can_queue - num) < 0) {
dev_dbg(&isci_host->pdev->dev,
"%s: isci_host->can_queue = %d\n",
__func__,
isci_host->can_queue);
ret = -SAS_QUEUE_FULL;
} else
isci_host->can_queue -= num;
spin_unlock_irqrestore(&isci_host->queue_lock, flags);
return ret;
}
static inline void isci_host_can_dequeue(
struct isci_host *isci_host,
int num)
{
unsigned long flags;
spin_lock_irqsave(&isci_host->queue_lock, flags);
isci_host->can_queue += num;
spin_unlock_irqrestore(&isci_host->queue_lock, flags);
}
/**
* isci_host_from_sas_ha() - This accessor retrieves the isci_host object
* reference from the Linux sas_ha_struct reference.
* @ha_struct,: This parameter points to the Linux sas_ha_struct object
*
* A reference to the associated isci_host structure.
*/
#define isci_host_from_sas_ha(ha_struct) \
((struct isci_host *)(ha_struct)->lldd_ha)
/**
* isci_host_scan_finished() -
*
* This function is one of the SCSI Host Template functions. The SCSI midlayer
* calls this function during a target scan, approx. once every 10 millisecs.
*/
int isci_host_scan_finished(
struct Scsi_Host *,
unsigned long);
/**
* isci_host_scan_start() -
*
* This function is one of the SCSI Host Template function, called by the SCSI
* mid layer berfore a target scan begins. The core library controller start
* routine is called from here.
*/
void isci_host_scan_start(
struct Scsi_Host *);
/**
* isci_host_start_complete() -
*
* This function is called by the core library, through the ISCI Module, to
* indicate controller start status.
*/
void isci_host_start_complete(
struct isci_host *,
enum sci_status);
void isci_host_stop_complete(
struct isci_host *isci_host,
enum sci_status completion_status);
int isci_host_init(struct isci_host *);
void isci_host_init_controller_names(
struct isci_host *isci_host,
unsigned int controller_idx);
void isci_host_deinit(
struct isci_host *);
void isci_host_port_link_up(
struct isci_host *,
struct scic_sds_port *,
struct scic_sds_phy *);
int isci_host_dev_found(struct domain_device *);
void isci_host_remote_device_start_complete(
struct isci_host *,
struct isci_remote_device *,
enum sci_status);
#endif /* !defined(_SCI_HOST_H_) */

613
drivers/scsi/isci/init.c Normal file
View File

@ -0,0 +1,613 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/string.h>
#include "isci.h"
#include "task.h"
#include "sci_controller_constants.h"
#include "scic_remote_device.h"
#include "sci_environment.h"
static struct scsi_transport_template *isci_transport_template;
struct kmem_cache *isci_kmem_cache;
static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
{ PCI_VDEVICE(INTEL, 0x1D61),},
{ PCI_VDEVICE(INTEL, 0x1D63),},
{ PCI_VDEVICE(INTEL, 0x1D65),},
{ PCI_VDEVICE(INTEL, 0x1D67),},
{ PCI_VDEVICE(INTEL, 0x1D69),},
{ PCI_VDEVICE(INTEL, 0x1D6B),},
{ PCI_VDEVICE(INTEL, 0x1D60),},
{ PCI_VDEVICE(INTEL, 0x1D62),},
{ PCI_VDEVICE(INTEL, 0x1D64),},
{ PCI_VDEVICE(INTEL, 0x1D66),},
{ PCI_VDEVICE(INTEL, 0x1D68),},
{ PCI_VDEVICE(INTEL, 0x1D6A),},
{}
};
static int __devinit isci_pci_probe(
struct pci_dev *pdev,
const struct pci_device_id *device_id_p);
static void __devexit isci_pci_remove(struct pci_dev *pdev);
MODULE_DEVICE_TABLE(pci, isci_id_table);
static struct pci_driver isci_pci_driver = {
.name = DRV_NAME,
.id_table = isci_id_table,
.probe = isci_pci_probe,
.remove = __devexit_p(isci_pci_remove),
};
/* linux isci specific settings */
int loglevel = 3;
module_param(loglevel, int, S_IRUGO | S_IWUSR);
#if defined(CONFIG_PBG_HBA_A0)
int isci_si_rev = ISCI_SI_REVA0;
#elif defined(CONFIG_PBG_HBA_A2)
int isci_si_rev = ISCI_SI_REVA2;
#else
int isci_si_rev = ISCI_SI_REVB0;
#endif
module_param(isci_si_rev, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(isci_si_rev, "override default si rev (0: A0 1: A2 2: B0)");
static struct scsi_host_template isci_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.slave_destroy = sas_slave_destroy,
.scan_finished = isci_host_scan_finished,
.scan_start = isci_host_scan_start,
.change_queue_depth = sas_change_queue_depth,
.change_queue_type = sas_change_queue_type,
.bios_param = sas_bios_param,
.can_queue = ISCI_CAN_QUEUE_VAL,
.cmd_per_lun = 1,
.this_id = -1,
.sg_tablesize = SG_ALL,
.max_sectors = SCSI_DEFAULT_MAX_SECTORS,
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = sas_eh_device_reset_handler,
.eh_bus_reset_handler = isci_bus_reset_handler,
.slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
};
static struct sas_domain_function_template isci_transport_ops = {
/* The class calls these to notify the LLDD of an event. */
.lldd_port_formed = isci_port_formed,
.lldd_port_deformed = isci_port_deformed,
/* The class calls these when a device is found or gone. */
.lldd_dev_found = isci_remote_device_found,
.lldd_dev_gone = isci_remote_device_gone,
.lldd_execute_task = isci_task_execute_task,
/* Task Management Functions. Must be called from process context. */
.lldd_abort_task = isci_task_abort_task,
.lldd_abort_task_set = isci_task_abort_task_set,
.lldd_clear_aca = isci_task_clear_aca,
.lldd_clear_task_set = isci_task_clear_task_set,
.lldd_I_T_nexus_reset = isci_task_I_T_nexus_reset,
.lldd_lu_reset = isci_task_lu_reset,
.lldd_query_task = isci_task_query_task,
/* Port and Adapter management */
.lldd_clear_nexus_port = isci_task_clear_nexus_port,
.lldd_clear_nexus_ha = isci_task_clear_nexus_ha,
/* Phy management */
.lldd_control_phy = isci_phy_control,
};
/******************************************************************************
* P R O T E C T E D M E T H O D S
******************************************************************************/
/**
* isci_register_sas_ha() - This method initializes various lldd
* specific members of the sas_ha struct and calls the libsas
* sas_register_ha() function.
* @isci_host: This parameter specifies the lldd specific wrapper for the
* libsas sas_ha struct.
*
* This method returns an error code indicating sucess or failure. The user
* should check for possible memory allocation error return otherwise, a zero
* indicates success.
*/
static int isci_register_sas_ha(struct isci_host *isci_host)
{
int i;
struct sas_ha_struct *sas_ha = &(isci_host->sas_ha);
struct asd_sas_phy **sas_phys;
struct asd_sas_port **sas_ports;
sas_phys = devm_kzalloc(&isci_host->pdev->dev,
SCI_MAX_PHYS * sizeof(void *),
GFP_KERNEL);
if (!sas_phys)
return -ENOMEM;
sas_ports = devm_kzalloc(&isci_host->pdev->dev,
SCI_MAX_PORTS * sizeof(void *),
GFP_KERNEL);
if (!sas_ports)
return -ENOMEM;
/*----------------- Libsas Initialization Stuff----------------------
* Set various fields in the sas_ha struct:
*/
sas_ha->sas_ha_name = DRV_NAME;
sas_ha->lldd_module = THIS_MODULE;
sas_ha->sas_addr = &(isci_host->sas_addr[0]);
/* set the array of phy and port structs. */
for (i = 0; i < SCI_MAX_PHYS; i++) {
sas_phys[i] = &(isci_host->phys[i].sas_phy);
sas_ports[i] = &(isci_host->sas_ports[i]);
}
sas_ha->sas_phy = sas_phys;
sas_ha->sas_port = sas_ports;
sas_ha->num_phys = SCI_MAX_PHYS;
sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL;
sas_ha->lldd_max_execute_num = 1;
sas_ha->strict_wide_ports = 1;
sas_register_ha(sas_ha);
return 0;
}
static void isci_unregister_sas_ha(struct isci_host *isci_host)
{
if (!isci_host)
return;
sas_unregister_ha(&(isci_host->sas_ha));
sas_remove_host(isci_host->shost);
scsi_remove_host(isci_host->shost);
scsi_host_put(isci_host->shost);
}
static int __devinit isci_pci_init(struct pci_dev *pdev)
{
int err, bar_num, bar_mask;
void __iomem * const *iomap;
err = pcim_enable_device(pdev);
if (err) {
dev_err(&pdev->dev,
"failed enable PCI device %s!\n",
pci_name(pdev));
return err;
}
for (bar_num = 0; bar_num < SCI_PCI_BAR_COUNT; bar_num++)
bar_mask |= 1 << (bar_num * 2);
err = pcim_iomap_regions(pdev, bar_mask, DRV_NAME);
if (err)
return err;
iomap = pcim_iomap_table(pdev);
if (!iomap)
return -ENOMEM;
pci_set_master(pdev);
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (err) {
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (err)
return err;
}
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
if (err) {
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (err)
return err;
}
return 0;
}
static struct isci_host *isci_host_by_id(struct pci_dev *pdev, int id)
{
struct isci_host *h;
for_each_isci_host(h, pdev)
if (h->id == id)
return h;
return NULL;
}
static int num_controllers(struct pci_dev *pdev)
{
/* bar size alone can tell us if we are running with a dual controller
* part, no need to trust revision ids that might be under broken firmware
* control
*/
resource_size_t scu_bar_size = pci_resource_len(pdev, SCI_SCU_BAR*2);
resource_size_t smu_bar_size = pci_resource_len(pdev, SCI_SMU_BAR*2);
if (scu_bar_size >= SCI_SCU_BAR_SIZE*SCI_MAX_CONTROLLERS &&
smu_bar_size >= SCI_SMU_BAR_SIZE*SCI_MAX_CONTROLLERS)
return SCI_MAX_CONTROLLERS;
else
return 1;
}
static int isci_setup_interrupts(struct pci_dev *pdev)
{
int err, i, num_msix;
struct isci_pci_info *pci_info = to_pci_info(pdev);
/*
* Determine the number of vectors associated with this
* PCI function.
*/
num_msix = num_controllers(pdev) * SCI_NUM_MSI_X_INT;
for (i = 0; i < num_msix; i++)
pci_info->msix_entries[i].entry = i;
err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix);
if (err)
goto intx;
for (i = 0; i < num_msix; i++) {
int id = i / SCI_NUM_MSI_X_INT;
struct msix_entry *msix = &pci_info->msix_entries[i];
struct isci_host *isci_host = isci_host_by_id(pdev, id);
BUG_ON(!isci_host);
/* @todo: need to handle error case. */
err = devm_request_irq(&pdev->dev, msix->vector, isci_isr, 0,
DRV_NAME"-msix", isci_host);
if (!err)
continue;
dev_info(&pdev->dev, "msix setup failed falling back to intx\n");
while (i--) {
id = i / SCI_NUM_MSI_X_INT;
isci_host = isci_host_by_id(pdev, id);
msix = &pci_info->msix_entries[i];
devm_free_irq(&pdev->dev, msix->vector, isci_host);
}
pci_disable_msix(pdev);
goto intx;
}
return 0;
intx:
err = devm_request_irq(&pdev->dev, pdev->irq, isci_legacy_isr,
IRQF_SHARED, DRV_NAME"-intx", pdev);
return err;
}
/**
* isci_parse_oem_parameters() - This method will take OEM parameters
* from the module init parameters and copy them to oem_params. This will
* only copy values that are not set to the module parameter default values
* @oem_parameters: This parameter specifies the controller default OEM
* parameters. It is expected that this has been initialized to the default
* parameters for the controller
*
*
*/
enum sci_status isci_parse_oem_parameters(union scic_oem_parameters *oem_params,
int scu_index,
struct isci_firmware *fw)
{
int i;
/* check for valid inputs */
if (!(scu_index >= 0
&& scu_index < SCI_MAX_CONTROLLERS
&& oem_params != NULL)) {
return SCI_FAILURE;
}
for (i = 0; i < SCI_MAX_PHYS; i++) {
int array_idx = i + (SCI_MAX_PHYS * scu_index);
u64 sas_addr = fw->sas_addrs[array_idx];
if (sas_addr != 0) {
oem_params->sds1.phys[i].sas_address.low =
(u32)(sas_addr & 0xffffffff);
oem_params->sds1.phys[i].sas_address.high =
(u32)((sas_addr >> 32) & 0xffffffff);
}
}
for (i = 0; i < SCI_MAX_PORTS; i++) {
int array_idx = i + (SCI_MAX_PORTS * scu_index);
u32 pmask = fw->phy_masks[array_idx];
oem_params->sds1.ports[i].phy_mask = pmask;
}
return SCI_SUCCESS;
}
/**
* isci_parse_user_parameters() - This method will take user parameters
* from the module init parameters and copy them to user_params. This will
* only copy values that are not set to the module parameter default values
* @user_parameters: This parameter specifies the controller default user
* parameters. It is expected that this has been initialized to the default
* parameters for the controller
*
*
*/
enum sci_status isci_parse_user_parameters(
union scic_user_parameters *user_params,
int scu_index,
struct isci_firmware *fw)
{
int i;
if (!(scu_index >= 0
&& scu_index < SCI_MAX_CONTROLLERS
&& user_params != NULL)) {
return SCI_FAILURE;
}
for (i = 0; i < SCI_MAX_PORTS; i++) {
int array_idx = i + (SCI_MAX_PORTS * scu_index);
u32 gen = fw->phy_gens[array_idx];
user_params->sds1.phys[i].max_speed_generation = gen;
}
return SCI_SUCCESS;
}
static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
{
struct isci_host *isci_host;
struct Scsi_Host *shost;
int err;
isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL);
if (!isci_host)
return NULL;
isci_host->pdev = pdev;
isci_host->id = id;
shost = scsi_host_alloc(&isci_sht, sizeof(void *));
if (!shost)
return NULL;
isci_host->shost = shost;
err = isci_host_init(isci_host);
if (err)
goto err_shost;
SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha;
isci_host->sas_ha.core.shost = shost;
shost->transportt = isci_transport_template;
shost->max_id = ~0;
shost->max_lun = ~0;
shost->max_cmd_len = MAX_COMMAND_SIZE;
err = scsi_add_host(shost, &pdev->dev);
if (err)
goto err_shost;
err = isci_register_sas_ha(isci_host);
if (err)
goto err_shost_remove;
return isci_host;
err_shost_remove:
scsi_remove_host(shost);
err_shost:
scsi_host_put(shost);
return NULL;
}
static void check_si_rev(struct pci_dev *pdev)
{
if (num_controllers(pdev) > 1)
isci_si_rev = ISCI_SI_REVB0;
else {
switch (pdev->revision) {
case 0:
case 1:
/* if the id is ambiguous don't update isci_si_rev */
break;
case 3:
isci_si_rev = ISCI_SI_REVA2;
break;
default:
case 4:
isci_si_rev = ISCI_SI_REVB0;
break;
}
}
dev_info(&pdev->dev, "driver configured for %s silicon (rev: %d)\n",
isci_si_rev == ISCI_SI_REVA0 ? "A0" :
isci_si_rev == ISCI_SI_REVA2 ? "A2" : "B0", pdev->revision);
}
static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct isci_pci_info *pci_info;
int err, i;
struct isci_host *isci_host;
check_si_rev(pdev);
pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
if (!pci_info)
return -ENOMEM;
pci_set_drvdata(pdev, pci_info);
err = isci_pci_init(pdev);
if (err)
return err;
for (i = 0; i < num_controllers(pdev); i++) {
struct isci_host *h = isci_host_alloc(pdev, i);
if (!h) {
err = -ENOMEM;
goto err_host_alloc;
}
h->next = pci_info->hosts;
pci_info->hosts = h;
}
err = isci_setup_interrupts(pdev);
if (err)
goto err_host_alloc;
for_each_isci_host(isci_host, pdev)
scsi_scan_host(isci_host->shost);
return 0;
err_host_alloc:
for_each_isci_host(isci_host, pdev)
isci_unregister_sas_ha(isci_host);
return err;
}
static void __devexit isci_pci_remove(struct pci_dev *pdev)
{
struct isci_host *isci_host;
for_each_isci_host(isci_host, pdev) {
isci_unregister_sas_ha(isci_host);
isci_host_deinit(isci_host);
scic_controller_disable_interrupts(isci_host->core_controller);
}
}
static __init int isci_init(void)
{
int err = -ENOMEM;
pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
isci_kmem_cache = kmem_cache_create(DRV_NAME,
sizeof(struct isci_remote_device) +
scic_remote_device_get_object_size(),
0, 0, NULL);
if (!isci_kmem_cache)
return err;
isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
if (!isci_transport_template)
goto err_kmem;
err = pci_register_driver(&isci_pci_driver);
if (err)
goto err_sas;
return 0;
err_sas:
sas_release_transport(isci_transport_template);
err_kmem:
kmem_cache_destroy(isci_kmem_cache);
return err;
}
static __exit void isci_exit(void)
{
pci_unregister_driver(&isci_pci_driver);
sas_release_transport(isci_transport_template);
kmem_cache_destroy(isci_kmem_cache);
}
MODULE_LICENSE("Dual BSD/GPL");
MODULE_FIRMWARE(ISCI_FW_NAME);
module_init(isci_init);
module_exit(isci_exit);

138
drivers/scsi/isci/isci.h Normal file
View File

@ -0,0 +1,138 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the isci_module object definition.
*
* isci.h
*/
#if !defined(_SCI_MODULE_H_)
#define _SCI_MODULE_H_
/**
* This file contains the SCI low level driver interface to the SCI and Libsas
* Libraries.
*
* isci.h
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/firmware.h>
#include <linux/bug.h>
#include <scsi/libsas.h>
#include <scsi/scsi.h>
#include "sci_types.h"
#include "sci_base_controller.h"
#include "scic_controller.h"
#include "host.h"
#include "timers.h"
#include "sci_status.h"
extern int loglevel;
extern struct kmem_cache *isci_kmem_cache;
#define ISCI_FW_NAME "isci/isci_firmware.bin"
#define ISCI_FIRMWARE_MIN_SIZE 149
#define ISCI_FW_IDSIZE 12
#define ISCI_FW_VER_OFS ISCI_FW_IDSIZE
#define ISCI_FW_SUBVER_OFS ISCI_FW_VER_OFS + 1
#define ISCI_FW_DATA_OFS ISCI_FW_SUBVER_OFS + 1
#define ISCI_FW_HDR_PHYMASK 0x1
#define ISCI_FW_HDR_PHYGEN 0x2
#define ISCI_FW_HDR_SASADDR 0x3
#define ISCI_FW_HDR_EOF 0xff
struct isci_firmware {
const u8 *id;
u8 version;
u8 subversion;
const u32 *phy_masks;
u8 phy_masks_size;
const u32 *phy_gens;
u8 phy_gens_size;
const u64 *sas_addrs;
u8 sas_addrs_size;
};
irqreturn_t isci_isr(int vec, void *data);
irqreturn_t isci_legacy_isr(int vec, void *data);
enum sci_status isci_parse_oem_parameters(
union scic_oem_parameters *oem_params,
int scu_index,
struct isci_firmware *fw);
enum sci_status isci_parse_user_parameters(
union scic_user_parameters *user_params,
int scu_index,
struct isci_firmware *fw);
#ifdef ISCI_SLAVE_ALLOC
extern int ISCI_SLAVE_ALLOC(struct scsi_device *scsi_dev);
#endif /* ISCI_SLAVE_ALLOC */
#ifdef ISCI_SLAVE_DESTROY
extern void ISCI_SLAVE_DESTROY(struct scsi_device *scsi_dev);
#endif /* ISCI_SLAVE_DESTROY */
#endif /* !defined(_SCI_MODULE_H_) */

179
drivers/scsi/isci/phy.c Normal file
View File

@ -0,0 +1,179 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "isci.h"
#include "phy.h"
#include "scic_port.h"
#include "scic_config_parameters.h"
/**
* isci_phy_init() - This function is called by the probe function to
* initialize the phy objects. This func assumes that the isci_port objects
* associated with the SCU have been initialized.
* @isci_phy: This parameter specifies the isci_phy object to initialize
* @isci_host: This parameter specifies the parent SCU host object for this
* isci_phy
* @index: This parameter specifies which SCU phy associates with this
* isci_phy. Generally, SCU phy 0 relates isci_phy 0, etc.
*
*/
void isci_phy_init(
struct isci_phy *phy,
struct isci_host *isci_host,
int index)
{
struct scic_sds_controller *controller = isci_host->core_controller;
struct scic_sds_phy *scic_phy;
union scic_oem_parameters oem_parameters;
enum sci_status status = SCI_SUCCESS;
/*--------------- SCU_Phy Initialization Stuff -----------------------*/
status = scic_controller_get_phy_handle(controller, index, &scic_phy);
if (status == SCI_SUCCESS) {
sci_object_set_association(scic_phy, (void *)phy);
phy->sci_phy_handle = scic_phy;
} else
dev_err(&isci_host->pdev->dev,
"failed scic_controller_get_phy_handle\n");
scic_oem_parameters_get(controller, &oem_parameters);
phy->sas_addr[0] = oem_parameters.sds1.phys[index].sas_address.low
& 0xFF;
phy->sas_addr[1] = (oem_parameters.sds1.phys[index].sas_address.low
>> 8) & 0xFF;
phy->sas_addr[2] = (oem_parameters.sds1.phys[index].sas_address.low
>> 16) & 0xFF;
phy->sas_addr[3] = (oem_parameters.sds1.phys[index].sas_address.low
>> 24) & 0xFF;
phy->sas_addr[4] = oem_parameters.sds1.phys[index].sas_address.high
& 0xFF;
phy->sas_addr[5] = (oem_parameters.sds1.phys[index].sas_address.high
>> 8) & 0xFF;
phy->sas_addr[6] = (oem_parameters.sds1.phys[index].sas_address.high
>> 16) & 0xFF;
phy->sas_addr[7] = (oem_parameters.sds1.phys[index].sas_address.high
>> 24) & 0xFF;
phy->isci_port = NULL;
phy->sas_phy.enabled = 0;
phy->sas_phy.id = index;
phy->sas_phy.sas_addr = &phy->sas_addr[0];
phy->sas_phy.frame_rcvd = (u8 *)&phy->frame_rcvd;
phy->sas_phy.ha = &isci_host->sas_ha;
phy->sas_phy.lldd_phy = phy;
phy->sas_phy.enabled = 1;
phy->sas_phy.class = SAS;
phy->sas_phy.iproto = SAS_PROTOCOL_ALL;
phy->sas_phy.tproto = 0;
phy->sas_phy.type = PHY_TYPE_PHYSICAL;
phy->sas_phy.role = PHY_ROLE_INITIATOR;
phy->sas_phy.oob_mode = OOB_NOT_CONNECTED;
phy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;
memset((u8 *)&phy->frame_rcvd, 0, sizeof(phy->frame_rcvd));
}
/**
* isci_phy_control() - This function is one of the SAS Domain Template
* functions. This is a phy management function.
* @phy: This parameter specifies the sphy being controlled.
* @func: This parameter specifies the phy control function being invoked.
* @buf: This parameter is specific to the phy function being invoked.
*
* status, zero indicates success.
*/
int isci_phy_control(
struct asd_sas_phy *phy,
enum phy_func func,
void *buf)
{
int ret = TMF_RESP_FUNC_COMPLETE;
struct isci_phy *isci_phy_ptr = (struct isci_phy *)phy->lldd_phy;
struct isci_port *isci_port_ptr = NULL;
if (isci_phy_ptr != NULL)
isci_port_ptr = isci_phy_ptr->isci_port;
if ((isci_phy_ptr == NULL) || (isci_port_ptr == NULL)) {
pr_err("%s: asd_sas_phy %p: lldd_phy %p or "
"isci_port %p == NULL!\n",
__func__, phy, isci_phy_ptr, isci_port_ptr);
return TMF_RESP_FUNC_FAILED;
}
pr_debug("%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
__func__, phy, func, buf, isci_phy_ptr, isci_port_ptr);
switch (func) {
case PHY_FUNC_HARD_RESET:
case PHY_FUNC_LINK_RESET:
/* Perform the port reset. */
ret = isci_port_perform_hard_reset(isci_port_ptr, isci_phy_ptr);
break;
case PHY_FUNC_DISABLE:
default:
pr_debug("%s: phy %p; func %d NOT IMPLEMENTED!\n",
__func__, phy, func);
ret = TMF_RESP_FUNC_FAILED;
break;
}
return ret;
}

104
drivers/scsi/isci/phy.h Normal file
View File

@ -0,0 +1,104 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(_ISCI_PHY_H_)
#define _ISCI_PHY_H_
#include "port.h"
#include "host.h"
#include <scsi/libsas.h>
/**
* struct isci_phy - This class implements the ISCI specific representation of
* the phy object.
*
*
*/
struct isci_phy {
struct scic_sds_phy *sci_phy_handle;
struct asd_sas_phy sas_phy;
struct sas_identify_frame *frame;
struct isci_port *isci_port;
u8 sas_addr[SAS_ADDR_SIZE];
union {
u8 aif[sizeof(struct sci_sas_identify_address_frame)];
u8 fis[sizeof(struct sata_fis_reg_d2h)];
} frame_rcvd;
};
#define to_isci_phy(p) \
container_of(p, struct isci_phy, sas_phy);
struct isci_host;
void isci_phy_init(
struct isci_phy *phy,
struct isci_host *isci_host,
int index);
int isci_phy_control(
struct asd_sas_phy *phy,
enum phy_func func,
void *buf);
#endif /* !defined(_ISCI_PHY_H_) */

484
drivers/scsi/isci/port.c Normal file
View File

@ -0,0 +1,484 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the isci port implementation.
*
*
*/
#include <linux/workqueue.h>
#include "isci.h"
#include "scic_io_request.h"
#include "scic_remote_device.h"
#include "scic_phy.h"
#include "scic_sds_phy.h"
#include "scic_port.h"
#include "port.h"
#include "request.h"
static void isci_port_change_state(
struct isci_port *isci_port,
enum isci_status status);
/**
* isci_port_init() - This function initializes the given isci_port object.
* @isci_port: This parameter specifies the port object to be initialized.
* @isci_host: This parameter specifies parent controller object for the port.
* @index: This parameter specifies which SCU port the isci_port associates
* with. Generally, SCU port 0 relates to isci_port 0, etc.
*
*/
void isci_port_init(
struct isci_port *isci_port,
struct isci_host *isci_host,
int index)
{
struct scic_sds_port *scic_port;
struct scic_sds_controller *controller = isci_host->core_controller;
INIT_LIST_HEAD(&isci_port->remote_dev_list);
INIT_LIST_HEAD(&isci_port->domain_dev_list);
spin_lock_init(&isci_port->remote_device_lock);
spin_lock_init(&isci_port->state_lock);
init_completion(&isci_port->start_complete);
isci_port->isci_host = isci_host;
isci_port_change_state(isci_port, isci_freed);
(void)scic_controller_get_port_handle(controller, index, &scic_port);
sci_object_set_association(scic_port, isci_port);
isci_port->sci_port_handle = scic_port;
}
/**
* isci_port_get_state() - This function gets the status of the port object.
* @isci_port: This parameter points to the isci_port object
*
* status of the object as a isci_status enum.
*/
enum isci_status isci_port_get_state(
struct isci_port *isci_port)
{
return isci_port->status;
}
static void isci_port_change_state(
struct isci_port *isci_port,
enum isci_status status)
{
unsigned long flags;
dev_dbg(&isci_port->isci_host->pdev->dev,
"%s: isci_port = %p, state = 0x%x\n",
__func__, isci_port, status);
spin_lock_irqsave(&isci_port->state_lock, flags);
isci_port->status = status;
spin_unlock_irqrestore(&isci_port->state_lock, flags);
}
void isci_port_bc_change_received(
struct isci_host *isci_host,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
struct isci_phy *isci_phy =
(struct isci_phy *)sci_object_get_association(phy);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_phy = %p, sas_phy = %p\n",
__func__,
isci_phy,
&isci_phy->sas_phy);
isci_host->sas_ha.notify_port_event(
&isci_phy->sas_phy,
PORTE_BROADCAST_RCVD
);
scic_port_enable_broadcast_change_notification(port);
}
/**
* isci_port_link_up() - This function is called by the sci core when a link
* becomes active. the identify address frame is retrieved from the core and
* a notify port event is sent to libsas.
* @isci_host: This parameter specifies the isci host object.
* @port: This parameter specifies the sci port with the active link.
* @phy: This parameter specifies the sci phy with the active link.
*
*/
void isci_port_link_up(
struct isci_host *isci_host,
struct scic_sds_port *port,
struct scic_sds_phy *phy)
{
unsigned long flags;
struct scic_port_properties properties;
struct isci_phy *isci_phy
= (struct isci_phy *)sci_object_get_association(phy);
struct isci_port *isci_port
= (struct isci_port *)sci_object_get_association(port);
enum sci_status call_status;
unsigned long success = true;
BUG_ON(isci_phy->isci_port != NULL);
isci_phy->isci_port = isci_port;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p\n",
__func__, isci_port);
spin_lock_irqsave(&isci_phy->sas_phy.frame_rcvd_lock, flags);
isci_port_change_state(isci_phy->isci_port, isci_starting);
scic_port_get_properties(port, &properties);
if (properties.remote.protocols.u.bits.stp_target) {
struct scic_sata_phy_properties sata_phy_properties;
isci_phy->sas_phy.oob_mode = SATA_OOB_MODE;
/* Get a copy of the signature fis for libsas */
call_status = scic_sata_phy_get_properties(phy,
&sata_phy_properties);
/*
* XXX I am concerned about this "assert". shouldn't we
* handle the return appropriately?
*/
BUG_ON(call_status != SCI_SUCCESS);
memcpy(isci_phy->frame_rcvd.fis,
&sata_phy_properties.signature_fis,
sizeof(struct sata_fis_reg_d2h));
isci_phy->sas_phy.frame_rcvd_size = sizeof(struct sata_fis_reg_d2h);
/*
* For direct-attached SATA devices, the SCI core will
* automagically assign a SAS address to the end device
* for the purpose of creating a port. This SAS address
* will not be the same as assigned to the PHY and needs
* to be obtained from struct scic_port_properties properties.
*/
BUG_ON(((size_t)SAS_ADDR_SIZE / 2)
!= sizeof(properties.remote.sas_address.low));
memcpy(&isci_phy->sas_phy.attached_sas_addr[0],
&properties.remote.sas_address.low,
SAS_ADDR_SIZE / 2);
memcpy(&isci_phy->sas_phy.attached_sas_addr[4],
&properties.remote.sas_address.high,
SAS_ADDR_SIZE / 2);
} else if (properties.remote.protocols.u.bits.ssp_target ||
properties.remote.protocols.u.bits.smp_target) {
struct scic_sas_phy_properties sas_phy_properties;
isci_phy->sas_phy.oob_mode = SAS_OOB_MODE;
/* Get a copy of the identify address frame for libsas */
call_status = scic_sas_phy_get_properties(phy,
&sas_phy_properties);
BUG_ON(call_status != SCI_SUCCESS);
memcpy(isci_phy->frame_rcvd.aif,
&(sas_phy_properties.received_iaf),
sizeof(struct sci_sas_identify_address_frame));
isci_phy->sas_phy.frame_rcvd_size
= sizeof(struct sci_sas_identify_address_frame);
/* Copy the attached SAS address from the IAF */
memcpy(isci_phy->sas_phy.attached_sas_addr,
((struct sas_identify_frame *)
(&isci_phy->frame_rcvd.aif))->sas_addr,
SAS_ADDR_SIZE);
} else {
dev_err(&isci_host->pdev->dev, "%s: unkown target\n", __func__);
success = false;
}
spin_unlock_irqrestore(&isci_phy->sas_phy.frame_rcvd_lock, flags);
/* Notify libsas that we have an address frame, if indeed
* we've found an SSP, SMP, or STP target */
if (success)
isci_host->sas_ha.notify_port_event(&isci_phy->sas_phy,
PORTE_BYTES_DMAED);
}
/**
* isci_port_link_down() - This function is called by the sci core when a link
* becomes inactive.
* @isci_host: This parameter specifies the isci host object.
* @phy: This parameter specifies the isci phy with the active link.
* @port: This parameter specifies the isci port with the active link.
*
*/
void isci_port_link_down(
struct isci_host *isci_host,
struct isci_phy *isci_phy,
struct isci_port *isci_port)
{
struct isci_remote_device *isci_device;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p\n", __func__, isci_port);
if (isci_port) {
/* check to see if this is the last phy on this port. */
if (isci_phy->sas_phy.port
&& isci_phy->sas_phy.port->num_phys == 1) {
/* change the state for all devices on this port.
* The next task sent to this device will be returned
* as SAS_TASK_UNDELIVERED, and the scsi mid layer
* will remove the target
*/
list_for_each_entry(isci_device,
&isci_port->remote_dev_list,
node) {
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p\n",
__func__, isci_device);
isci_remote_device_change_state(isci_device,
isci_stopping);
}
}
isci_port_change_state(isci_port, isci_stopping);
}
/* Notify libsas of the borken link, this will trigger calls to our
* isci_port_deformed and isci_dev_gone functions.
*/
sas_phy_disconnected(&isci_phy->sas_phy);
isci_host->sas_ha.notify_phy_event(&isci_phy->sas_phy,
PHYE_LOSS_OF_SIGNAL);
isci_phy->isci_port = NULL;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p - Done\n", __func__, isci_port);
}
/**
* isci_port_deformed() - This function is called by libsas when a port becomes
* inactive.
* @phy: This parameter specifies the libsas phy with the inactive port.
*
*/
void isci_port_deformed(
struct asd_sas_phy *phy)
{
pr_debug("%s: sas_phy = %p\n", __func__, phy);
}
/**
* isci_port_formed() - This function is called by libsas when a port becomes
* active.
* @phy: This parameter specifies the libsas phy with the active port.
*
*/
void isci_port_formed(
struct asd_sas_phy *phy)
{
pr_debug("%s: sas_phy = %p, sas_port = %p\n", __func__, phy, phy->port);
}
/**
* isci_port_ready() - This function is called by the sci core when a link
* becomes ready.
* @isci_host: This parameter specifies the isci host object.
* @port: This parameter specifies the sci port with the active link.
*
*/
void isci_port_ready(
struct isci_host *isci_host,
struct isci_port *isci_port)
{
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p\n", __func__, isci_port);
complete_all(&isci_port->start_complete);
isci_port_change_state(isci_port, isci_ready);
return;
}
/**
* isci_port_not_ready() - This function is called by the sci core when a link
* is not ready. All remote devices on this link will be removed if they are
* in the stopping state.
* @isci_host: This parameter specifies the isci host object.
* @port: This parameter specifies the sci port with the active link.
*
*/
void isci_port_not_ready(
struct isci_host *isci_host,
struct isci_port *isci_port)
{
dev_dbg(&isci_host->pdev->dev,
"%s: isci_port = %p\n", __func__, isci_port);
}
/**
* isci_port_hard_reset_complete() - This function is called by the sci core
* when the hard reset complete notification has been received.
* @port: This parameter specifies the sci port with the active link.
* @completion_status: This parameter specifies the core status for the reset
* process.
*
*/
void isci_port_hard_reset_complete(
struct isci_port *isci_port,
enum sci_status completion_status)
{
dev_dbg(&isci_port->isci_host->pdev->dev,
"%s: isci_port = %p, completion_status=%x\n",
__func__, isci_port, completion_status);
/* Save the status of the hard reset from the port. */
isci_port->hard_reset_status = completion_status;
complete_all(&isci_port->hard_reset_complete);
}
/**
* isci_port_perform_hard_reset() - This function is one of the SAS Domain
* Template functions. This is a phy management function.
* @isci_port:
* @isci_phy:
*
* status, TMF_RESP_FUNC_COMPLETE indicates success.
*/
int isci_port_perform_hard_reset(
struct isci_port *isci_port,
struct isci_phy *isci_phy)
{
enum sci_status status;
int ret = TMF_RESP_FUNC_COMPLETE;
unsigned long flags;
dev_dbg(&isci_port->isci_host->pdev->dev,
"%s: isci_port = %p\n",
__func__, isci_port);
BUG_ON(isci_port == NULL);
init_completion(&isci_port->hard_reset_complete);
spin_lock_irqsave(&isci_port->isci_host->scic_lock, flags);
#define ISCI_PORT_RESET_TIMEOUT SCIC_SDS_SIGNATURE_FIS_TIMEOUT
status = scic_port_hard_reset(isci_port->sci_port_handle,
ISCI_PORT_RESET_TIMEOUT);
spin_unlock_irqrestore(&isci_port->isci_host->scic_lock, flags);
if (status == SCI_SUCCESS) {
wait_for_completion(&isci_port->hard_reset_complete);
dev_dbg(&isci_port->isci_host->pdev->dev,
"%s: isci_port = %p; hard reset completion\n",
__func__, isci_port);
if (isci_port->hard_reset_status != SCI_SUCCESS)
ret = TMF_RESP_FUNC_FAILED;
} else {
ret = TMF_RESP_FUNC_FAILED;
dev_err(&isci_port->isci_host->pdev->dev,
"%s: isci_port = %p; scic_port_hard_reset call"
" failed 0x%x\n",
__func__, isci_port, status);
}
/* If the hard reset for the port has failed, consider this
* the same as link failures on all phys in the port.
*/
if (ret != TMF_RESP_FUNC_COMPLETE) {
BUG_ON(isci_port->isci_host == NULL);
dev_err(&isci_port->isci_host->pdev->dev,
"%s: isci_port = %p; hard reset failed "
"(0x%x) - sending link down to libsas for phy %p\n",
__func__,
isci_port,
isci_port->hard_reset_status,
isci_phy);
isci_port_link_down(isci_port->isci_host,
isci_phy,
isci_port);
}
return ret;
}

153
drivers/scsi/isci/port.h Normal file
View File

@ -0,0 +1,153 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* This file contains the isci_port object definition.
*
* port.h
*/
#if !defined(_ISCI_PORT_H_)
#define _ISCI_PORT_H_
struct isci_phy;
struct isci_host;
enum isci_status {
isci_freed = 0x00,
isci_starting = 0x01,
isci_ready = 0x02,
isci_ready_for_io = 0x03,
isci_stopping = 0x04,
isci_stopped = 0x05,
isci_host_quiesce = 0x06
};
/**
* struct isci_port - This class represents the port object used to internally
* represent libsas port objects. It also keeps a list of remote device
* objects.
*
*
*/
struct isci_port {
struct scic_sds_port *sci_port_handle;
enum isci_status status;
struct isci_host *isci_host;
struct asd_sas_port sas_port;
struct list_head remote_dev_list;
spinlock_t remote_device_lock;
spinlock_t state_lock;
struct list_head domain_dev_list;
struct completion start_complete;
struct completion hard_reset_complete;
enum sci_status hard_reset_status;
};
#define to_isci_port(p) \
container_of(p, struct isci_port, sas_port);
enum isci_status isci_port_get_state(
struct isci_port *isci_port);
void isci_port_formed(
struct asd_sas_phy *);
void isci_port_deformed(
struct asd_sas_phy *);
void isci_port_bc_change_received(
struct isci_host *isci_host,
struct scic_sds_port *port,
struct scic_sds_phy *phy);
void isci_port_link_up(
struct isci_host *isci_host,
struct scic_sds_port *port,
struct scic_sds_phy *phy);
void isci_port_link_down(
struct isci_host *isci_host,
struct isci_phy *isci_phy,
struct isci_port *port);
void isci_port_ready(
struct isci_host *isci_host,
struct isci_port *isci_port);
void isci_port_not_ready(
struct isci_host *isci_host,
struct isci_port *port);
void isci_port_init(
struct isci_port *port,
struct isci_host *host,
int index);
void isci_port_hard_reset_complete(
struct isci_port *isci_port,
enum sci_status completion_status);
int isci_port_perform_hard_reset(
struct isci_port *isci_port_ptr,
struct isci_phy *isci_phy_ptr);
#endif /* !defined(_ISCI_PORT_H_) */

View File

@ -0,0 +1,698 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "isci.h"
#include "scic_io_request.h"
#include "scic_remote_device.h"
#include "scic_phy.h"
#include "scic_port.h"
#include "port.h"
#include "remote_device.h"
#include "request.h"
#include "task.h"
/**
* isci_remote_device_deconstruct() - This function frees an isci_remote_device.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device to be freed.
*
*/
static void isci_remote_device_deconstruct(
struct isci_host *isci_host,
struct isci_remote_device *isci_device)
{
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
/* There should not be any outstanding io's. All paths to
* here should go through isci_remote_device_nuke_requests.
* If we hit this condition, we will need a way to complete
* io requests in process */
while (!list_empty(&isci_device->reqs_in_process)) {
dev_err(&isci_host->pdev->dev,
"%s: ** request list not empty! **\n", __func__);
BUG();
}
/* Remove all related references to this device and free
* the cache object.
*/
scic_remote_device_destruct(isci_device->sci_device_handle);
isci_device->domain_dev->lldd_dev = NULL;
list_del(&isci_device->node);
kmem_cache_free(isci_kmem_cache, isci_device);
}
/**
* isci_remote_device_construct() - This function calls the scic remote device
* construct and start functions, it waits on the remote device start
* completion.
* @port: This parameter specifies the isci port with the remote device.
* @isci_device: This parameter specifies the isci remote device
*
* status from the scic calls, the caller to this function should clean up
* resources as appropriate.
*/
static enum sci_status isci_remote_device_construct(
struct isci_port *port,
struct isci_remote_device *isci_device)
{
enum sci_status status = SCI_SUCCESS;
/* let the core do it's common constuction. */
scic_remote_device_construct(port->sci_port_handle,
isci_device->sci_device_handle);
/* let the core do it's device specific constuction. */
if (isci_device->domain_dev->parent &&
(isci_device->domain_dev->parent->dev_type == EDGE_DEV)) {
int i;
/* struct smp_response_discover discover_response; */
struct discover_resp discover_response;
struct domain_device *parent =
isci_device->domain_dev->parent;
struct expander_device *parent_ex = &parent->ex_dev;
for (i = 0; i < parent_ex->num_phys; i++) {
struct ex_phy *phy = &parent_ex->ex_phy[i];
if ((phy->phy_state == PHY_VACANT) ||
(phy->phy_state == PHY_NOT_PRESENT))
continue;
if (SAS_ADDR(phy->attached_sas_addr)
== SAS_ADDR(isci_device->domain_dev->sas_addr)) {
discover_response.attached_dev_type
= phy->attached_dev_type;
discover_response.linkrate
= phy->linkrate;
discover_response.attached_sata_host
= phy->attached_sata_host;
discover_response.attached_sata_dev
= phy->attached_sata_dev;
discover_response.attached_sata_ps
= phy->attached_sata_ps;
discover_response.iproto
= phy->attached_iproto >> 1;
discover_response.tproto
= phy->attached_tproto >> 1;
memcpy(
discover_response.attached_sas_addr,
phy->attached_sas_addr,
SAS_ADDR_SIZE
);
discover_response.attached_phy_id
= phy->attached_phy_id;
discover_response.change_count
= phy->phy_change_count;
discover_response.routing_attr
= phy->routing_attr;
discover_response.hmin_linkrate
= phy->phy->minimum_linkrate_hw;
discover_response.hmax_linkrate
= phy->phy->maximum_linkrate_hw;
discover_response.pmin_linkrate
= phy->phy->minimum_linkrate;
discover_response.pmax_linkrate
= phy->phy->maximum_linkrate;
}
}
dev_dbg(&port->isci_host->pdev->dev,
"%s: parent->dev_type = EDGE_DEV\n",
__func__);
status = scic_remote_device_ea_construct(
isci_device->sci_device_handle,
(struct smp_response_discover *)&discover_response
);
} else
status = scic_remote_device_da_construct(
isci_device->sci_device_handle
);
if (status != SCI_SUCCESS) {
dev_dbg(&port->isci_host->pdev->dev,
"%s: scic_remote_device_da_construct failed - "
"isci_device = %p\n",
__func__,
isci_device);
return status;
}
sci_object_set_association(
isci_device->sci_device_handle,
isci_device
);
BUG_ON(port->isci_host == NULL);
/* start the device. */
status = scic_remote_device_start(
isci_device->sci_device_handle,
ISCI_REMOTE_DEVICE_START_TIMEOUT
);
if (status != SCI_SUCCESS) {
dev_warn(&port->isci_host->pdev->dev,
"%s: scic_remote_device_start failed\n",
__func__);
return status;
}
return status;
}
/**
* isci_remote_device_nuke_requests() - This function terminates all requests
* for a given remote device.
* @isci_device: This parameter specifies the remote device
*
*/
void isci_remote_device_nuke_requests(
struct isci_remote_device *isci_device)
{
DECLARE_COMPLETION_ONSTACK(aborted_task_completion);
struct isci_host *isci_host;
isci_host = isci_device->isci_port->isci_host;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
/* Cleanup all requests pending for this device. */
isci_terminate_pending_requests(isci_host, isci_device, terminating);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p, done\n", __func__, isci_device);
}
/**
* This function builds the isci_remote_device when a libsas dev_found message
* is received.
* @isci_host: This parameter specifies the isci host object.
* @port: This parameter specifies the isci_port conected to this device.
*
* pointer to new isci_remote_device.
*/
static struct isci_remote_device *
isci_remote_device_alloc(struct isci_host *isci_host, struct isci_port *port)
{
struct isci_remote_device *isci_device;
struct scic_sds_remote_device *sci_dev;
isci_device = kmem_cache_zalloc(isci_kmem_cache, GFP_KERNEL);
if (!isci_device) {
dev_warn(&isci_host->pdev->dev, "%s: failed\n", __func__);
return NULL;
}
sci_dev = (struct scic_sds_remote_device *) &isci_device[1];
isci_device->sci_device_handle = sci_dev;
INIT_LIST_HEAD(&isci_device->reqs_in_process);
INIT_LIST_HEAD(&isci_device->node);
isci_device->host_quiesce = false;
spin_lock_init(&isci_device->state_lock);
spin_lock_init(&isci_device->host_quiesce_lock);
isci_remote_device_change_state(isci_device, isci_freed);
return isci_device;
}
/**
* isci_device_set_host_quiesce_lock_state() - This function sets the host I/O
* quiesce lock state for the remote_device object.
* @isci_device,: This parameter points to the isci_remote_device object
* @isci_device: This parameter specifies the new quiesce state.
*
*/
void isci_device_set_host_quiesce_lock_state(
struct isci_remote_device *isci_device,
bool lock_state)
{
unsigned long flags;
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
"%s: isci_device=%p, lock_state=%d\n",
__func__, isci_device, lock_state);
spin_lock_irqsave(&isci_device->host_quiesce_lock, flags);
isci_device->host_quiesce = lock_state;
spin_unlock_irqrestore(&isci_device->host_quiesce_lock, flags);
}
/**
* isci_remote_device_ready() - This function is called by the scic when the
* remote device is ready. We mark the isci device as ready and signal the
* waiting proccess.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device
*
*/
void isci_remote_device_ready(struct isci_remote_device *isci_device)
{
unsigned long flags;
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
/* device ready is actually a "ready for io" state. */
if ((isci_starting == isci_remote_device_get_state(isci_device)) ||
(isci_ready == isci_remote_device_get_state(isci_device))) {
spin_lock_irqsave(&isci_device->isci_port->remote_device_lock,
flags);
isci_remote_device_change_state(isci_device, isci_ready_for_io);
if (isci_device->completion)
complete(isci_device->completion);
spin_unlock_irqrestore(
&isci_device->isci_port->remote_device_lock,
flags);
}
}
/**
* isci_remote_device_not_ready() - This function is called by the scic when
* the remote device is not ready. We mark the isci device as ready (not
* "ready_for_io") and signal the waiting proccess.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device
*
*/
void isci_remote_device_not_ready(
struct isci_remote_device *isci_device,
u32 reason_code)
{
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
if (reason_code == SCIC_REMOTE_DEVICE_NOT_READY_STOP_REQUESTED)
isci_remote_device_change_state(isci_device, isci_stopping);
else
/* device ready is actually a "not ready for io" state. */
isci_remote_device_change_state(isci_device, isci_ready);
}
/**
* isci_remote_device_stop_complete() - This function is called by the scic
* when the remote device stop has completed. We mark the isci device as not
* ready and remove the isci remote device.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device.
* @status: This parameter specifies status of the completion.
*
*/
void isci_remote_device_stop_complete(
struct isci_host *isci_host,
struct isci_remote_device *isci_device,
enum sci_status status)
{
struct completion *completion = isci_device->completion;
dev_dbg(&isci_host->pdev->dev,
"%s: complete isci_device = %p, status = 0x%x\n",
__func__,
isci_device,
status);
isci_remote_device_change_state(isci_device, isci_stopped);
/* after stop, we can tear down resources. */
isci_remote_device_deconstruct(isci_host, isci_device);
/* notify interested parties. */
if (completion)
complete(completion);
}
/**
* isci_remote_device_start_complete() - This function is called by the scic
* when the remote device start has completed
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device.
* @status: This parameter specifies status of the completion.
*
*/
void isci_remote_device_start_complete(
struct isci_host *isci_host,
struct isci_remote_device *isci_device,
enum sci_status status)
{
}
/**
* isci_remote_device_stop() - This function is called internally to stop the
* remote device.
* @isci_host: This parameter specifies the isci host object.
* @isci_device: This parameter specifies the remote device.
*
* The status of the scic request to stop.
*/
enum sci_status isci_remote_device_stop(
struct isci_remote_device *isci_device)
{
enum sci_status status;
unsigned long flags;
DECLARE_COMPLETION_ONSTACK(completion);
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
isci_remote_device_change_state(isci_device, isci_stopping);
/* We need comfirmation that stop completed. */
isci_device->completion = &completion;
BUG_ON(isci_device->isci_port == NULL);
BUG_ON(isci_device->isci_port->isci_host == NULL);
spin_lock_irqsave(&isci_device->isci_port->isci_host->scic_lock, flags);
status = scic_remote_device_stop(
isci_device->sci_device_handle,
50
);
spin_unlock_irqrestore(&isci_device->isci_port->isci_host->scic_lock, flags);
/* Wait for the stop complete callback. */
if (status == SCI_SUCCESS)
wait_for_completion(&completion);
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
"%s: isci_device = %p - after completion wait\n",
__func__, isci_device);
isci_device->completion = NULL;
return status;
}
/**
* isci_remote_device_gone() - This function is called by libsas when a domain
* device is removed.
* @domain_device: This parameter specifies the libsas domain device.
*
*/
void isci_remote_device_gone(
struct domain_device *domain_dev)
{
struct isci_remote_device *isci_device = isci_dev_from_domain_dev(
domain_dev);
dev_err(&isci_device->isci_port->isci_host->pdev->dev,
"%s: domain_device = %p, isci_device = %p, isci_port = %p\n",
__func__, domain_dev, isci_device, isci_device->isci_port);
if (isci_device != NULL)
isci_remote_device_stop(isci_device);
}
/**
* isci_remote_device_found() - This function is called by libsas when a remote
* device is discovered. A remote device object is created and started. the
* function then sleeps until the sci core device started message is
* received.
* @domain_device: This parameter specifies the libsas domain device.
*
* status, zero indicates success.
*/
int isci_remote_device_found(struct domain_device *domain_dev)
{
unsigned long flags;
struct isci_host *isci_host;
struct isci_port *isci_port;
struct isci_phy *isci_phy;
struct asd_sas_port *sas_port;
struct asd_sas_phy *sas_phy;
struct isci_remote_device *isci_device;
enum sci_status status;
DECLARE_COMPLETION_ONSTACK(completion);
isci_host = isci_host_from_sas_ha(domain_dev->port->ha);
dev_dbg(&isci_host->pdev->dev,
"%s: domain_device = %p\n", __func__, domain_dev);
sas_port = domain_dev->port;
sas_phy = list_first_entry(&sas_port->phy_list, struct asd_sas_phy,
port_phy_el);
isci_phy = to_isci_phy(sas_phy);
isci_port = isci_phy->isci_port;
/* we are being called for a device on this port,
* so it has to come up eventually
*/
wait_for_completion(&isci_port->start_complete);
if ((isci_stopping == isci_port_get_state(isci_port)) ||
(isci_stopped == isci_port_get_state(isci_port)))
return -ENODEV;
isci_device = isci_remote_device_alloc(isci_host, isci_port);
INIT_LIST_HEAD(&isci_device->node);
domain_dev->lldd_dev = isci_device;
isci_device->domain_dev = domain_dev;
isci_device->isci_port = isci_port;
isci_remote_device_change_state(isci_device, isci_starting);
spin_lock_irqsave(&isci_port->remote_device_lock, flags);
list_add_tail(&isci_device->node, &isci_port->remote_dev_list);
/* for the device ready event. */
isci_device->completion = &completion;
status = isci_remote_device_construct(isci_port, isci_device);
spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
/* wait for the device ready callback. */
wait_for_completion(isci_device->completion);
isci_device->completion = NULL;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p\n",
__func__, isci_device);
if (status != SCI_SUCCESS) {
spin_lock_irqsave(&isci_port->remote_device_lock, flags);
isci_remote_device_deconstruct(
isci_host,
isci_device
);
spin_unlock_irqrestore(&isci_port->remote_device_lock, flags);
return -ENODEV;
}
wait_for_completion(&isci_host->start_complete);
return 0;
}
/**
* isci_device_is_reset_pending() - This function will check if there is any
* pending reset condition on the device.
* @request: This parameter is the isci_device object.
*
* true if there is a reset pending for the device.
*/
bool isci_device_is_reset_pending(
struct isci_host *isci_host,
struct isci_remote_device *isci_device)
{
struct isci_request *isci_request;
struct isci_request *tmp_req;
bool reset_is_pending = false;
unsigned long flags;
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p\n", __func__, isci_device);
spin_lock_irqsave(&isci_host->scic_lock, flags);
/* Check for reset on all pending requests. */
list_for_each_entry_safe(isci_request, tmp_req,
&isci_device->reqs_in_process, dev_node) {
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p request = %p\n",
__func__, isci_device, isci_request);
if (isci_request->ttype == io_task) {
unsigned long flags;
struct sas_task *task = isci_request_access_task(
isci_request);
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_NEED_DEV_RESET)
reset_is_pending = true;
spin_unlock_irqrestore(&task->task_state_lock, flags);
}
}
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
dev_dbg(&isci_host->pdev->dev,
"%s: isci_device = %p reset_is_pending = %d\n",
__func__, isci_device, reset_is_pending);
return reset_is_pending;
}
/**
* isci_device_clear_reset_pending() - This function will clear if any pending
* reset condition flags on the device.
* @request: This parameter is the isci_device object.
*
* true if there is a reset pending for the device.
*/
void isci_device_clear_reset_pending(struct isci_remote_device *isci_device)
{
struct isci_request *isci_request;
struct isci_request *tmp_req;
struct isci_host *isci_host = NULL;
unsigned long flags = 0;
/* FIXME more port gone confusion, and this time it makes the
* locking "fun"
*/
if (isci_device->isci_port != NULL)
isci_host = isci_device->isci_port->isci_host;
/*
* FIXME when the isci_host gets sorted out
* use dev_dbg()
*/
pr_debug("%s: isci_device=%p, isci_host=%p\n",
__func__, isci_device, isci_host);
if (isci_host != NULL)
spin_lock_irqsave(&isci_host->scic_lock, flags);
else
pr_err("%s: isci_device %p; isci_host == NULL!\n",
__func__, isci_device);
/* Clear reset pending on all pending requests. */
list_for_each_entry_safe(isci_request, tmp_req,
&isci_device->reqs_in_process, dev_node) {
/*
* FIXME when the conditional spinlock is gone
* change to dev_dbg()
*/
pr_debug("%s: isci_device = %p request = %p\n",
__func__, isci_device, isci_request);
if (isci_request->ttype == io_task) {
unsigned long flags2;
struct sas_task *task = isci_request_access_task(
isci_request);
spin_lock_irqsave(&task->task_state_lock, flags2);
task->task_state_flags &= ~SAS_TASK_NEED_DEV_RESET;
spin_unlock_irqrestore(&task->task_state_lock, flags2);
}
}
if (isci_host != NULL)
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
}
/**
* isci_remote_device_change_state() - This function gets the status of the
* remote_device object.
* @isci_device: This parameter points to the isci_remote_device object
*
* status of the object as a isci_status enum.
*/
void isci_remote_device_change_state(
struct isci_remote_device *isci_device,
enum isci_status status)
{
unsigned long flags;
dev_dbg(&isci_device->isci_port->isci_host->pdev->dev,
"%s: isci_device = %p, state = 0x%x",
__func__,
isci_device,
status);
spin_lock_irqsave(&isci_device->state_lock, flags);
isci_device->status = status;
spin_unlock_irqrestore(&isci_device->state_lock, flags);
}

View File

@ -0,0 +1,154 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(_ISCI_REMOTE_DEVICE_H_)
#define _ISCI_REMOTE_DEVICE_H_
#include "scic_user_callback.h"
struct isci_host;
struct scic_sds_remote_device;
struct isci_remote_device {
struct scic_sds_remote_device *sci_device_handle;
enum isci_status status;
struct isci_port *isci_port;
struct domain_device *domain_dev;
struct completion *completion;
struct list_head node;
struct list_head reqs_in_process;
struct work_struct stop_work;
spinlock_t state_lock;
spinlock_t host_quiesce_lock;
bool host_quiesce;
};
#define to_isci_remote_device(p) \
container_of(p, struct isci_remote_device, sci_remote_device);
#define ISCI_REMOTE_DEVICE_START_TIMEOUT 5000
/**
* This function gets the status of the remote_device object.
* @isci_device: This parameter points to the isci_remote_device object
*
* status of the object as a isci_status enum.
*/
static inline
enum isci_status isci_remote_device_get_state(
struct isci_remote_device *isci_device)
{
return (isci_device->host_quiesce)
? isci_host_quiesce
: isci_device->status;
}
/**
* isci_dev_from_domain_dev() - This accessor retrieves the remote_device
* object reference from the Linux domain_device reference.
* @domdev,: This parameter points to the Linux domain_device object .
*
* A reference to the associated isci remote device.
*/
#define isci_dev_from_domain_dev(domdev) \
((struct isci_remote_device *)(domdev)->lldd_dev)
void isci_remote_device_start_complete(
struct isci_host *,
struct isci_remote_device *,
enum sci_status);
void isci_remote_device_stop_complete(
struct isci_host *,
struct isci_remote_device *,
enum sci_status);
enum sci_status isci_remote_device_stop(
struct isci_remote_device *isci_device);
void isci_remote_device_nuke_requests(
struct isci_remote_device *isci_device);
void isci_remote_device_ready(
struct isci_remote_device *);
void isci_remote_device_not_ready(
struct isci_remote_device *,
u32);
void isci_remote_device_gone(
struct domain_device *domain_dev);
int isci_remote_device_found(
struct domain_device *domain_dev);
bool isci_device_is_reset_pending(
struct isci_host *isci_host,
struct isci_remote_device *isci_device);
void isci_device_clear_reset_pending(
struct isci_remote_device *isci_device);
void isci_device_set_host_quiesce_lock_state(
struct isci_remote_device *isci_device,
bool lock_state);
void isci_remote_device_change_state(
struct isci_remote_device *isci_device,
enum isci_status status);
#endif /* !defined(_ISCI_REMOTE_DEVICE_H_) */

1472
drivers/scsi/isci/request.c Normal file

File diff suppressed because it is too large Load Diff

429
drivers/scsi/isci/request.h Normal file
View File

@ -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.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(_ISCI_REQUEST_H_)
#define _ISCI_REQUEST_H_
#include "isci.h"
/**
* struct isci_request_status - This enum defines the possible states of an I/O
* request.
*
*
*/
enum isci_request_status {
unallocated = 0x00,
allocated = 0x01,
started = 0x02,
completed = 0x03,
aborting = 0x04,
aborted = 0x05,
terminating = 0x06
};
enum task_type {
io_task = 0,
tmf_task = 1
};
/**
* struct isci_request - This class represents the request object used to track
* IO, smp and TMF request internal. It wraps the SCIC request object.
*
*
*/
struct isci_request {
struct scic_sds_request *sci_request_handle;
enum isci_request_status status;
enum task_type ttype;
unsigned short io_tag;
bool complete_in_target;
union ttype_ptr_union {
struct sas_task *io_task_ptr; /* When ttype==io_task */
struct isci_tmf *tmf_task_ptr; /* When ttype==tmf_task */
} ttype_ptr;
struct isci_host *isci_host;
struct isci_remote_device *isci_device;
/* For use in the requests_to_{complete|abort} lists: */
struct list_head completed_node;
/* For use in the reqs_in_process list: */
struct list_head dev_node;
void *sci_request_mem_ptr;
spinlock_t state_lock;
dma_addr_t request_daddr;
dma_addr_t zero_scatter_daddr;
unsigned int num_sg_entries; /* returned by pci_alloc_sg */
unsigned int request_alloc_size; /* size of block from dma_pool_alloc */
/** Note: "io_request_completion" is completed in two different ways
* depending on whether this is a TMF or regular request.
* - TMF requests are completed in the thread that started them;
* - regular requests are completed in the request completion callback
* function.
* This difference in operation allows the aborter of a TMF request
* to be sure that once the TMF request completes, the I/O that the
* TMF was aborting is guaranteed to have completed.
*/
struct completion *io_request_completion;
};
/**
* This function gets the status of the request object.
* @request: This parameter points to the isci_request object
*
* status of the object as a isci_request_status enum.
*/
static inline
enum isci_request_status isci_request_get_state(
struct isci_request *isci_request)
{
BUG_ON(isci_request == NULL);
/*probably a bad sign... */
if (isci_request->status == unallocated)
dev_warn(&isci_request->isci_host->pdev->dev,
"%s: isci_request->status == unallocated\n",
__func__);
return isci_request->status;
}
/**
* isci_request_change_state() - This function sets the status of the request
* object.
* @request: This parameter points to the isci_request object
* @status: This Parameter is the new status of the object
*
*/
static inline enum isci_request_status isci_request_change_state(
struct isci_request *isci_request,
enum isci_request_status status)
{
enum isci_request_status old_state;
unsigned long flags;
dev_dbg(&isci_request->isci_host->pdev->dev,
"%s: isci_request = %p, state = 0x%x\n",
__func__,
isci_request,
status);
BUG_ON(isci_request == NULL);
spin_lock_irqsave(&isci_request->state_lock, flags);
old_state = isci_request->status;
isci_request->status = status;
spin_unlock_irqrestore(&isci_request->state_lock, flags);
return old_state;
}
/**
* isci_request_change_started_to_newstate() - This function sets the status of
* the request object.
* @request: This parameter points to the isci_request object
* @status: This Parameter is the new status of the object
*
* state previous to any change.
*/
static inline enum isci_request_status isci_request_change_started_to_newstate(
struct isci_request *isci_request,
struct completion *completion_ptr,
enum isci_request_status newstate)
{
enum isci_request_status old_state;
unsigned long flags;
BUG_ON(isci_request == NULL);
spin_lock_irqsave(&isci_request->state_lock, flags);
old_state = isci_request->status;
if (old_state == started) {
BUG_ON(isci_request->io_request_completion != NULL);
isci_request->io_request_completion = completion_ptr;
isci_request->status = newstate;
}
spin_unlock_irqrestore(&isci_request->state_lock, flags);
dev_dbg(&isci_request->isci_host->pdev->dev,
"%s: isci_request = %p, old_state = 0x%x\n",
__func__,
isci_request,
old_state);
return old_state;
}
/**
* isci_request_change_started_to_aborted() - This function sets the status of
* the request object.
* @request: This parameter points to the isci_request object
* @completion_ptr: This parameter is saved as the kernel completion structure
* signalled when the old request completes.
*
* state previous to any change.
*/
static inline enum isci_request_status isci_request_change_started_to_aborted(
struct isci_request *isci_request,
struct completion *completion_ptr)
{
return isci_request_change_started_to_newstate(
isci_request, completion_ptr, aborted
);
}
/**
* isci_request_free() - This function frees the request object.
* @isci_host: This parameter specifies the ISCI host object
* @isci_request: This parameter points to the isci_request object
*
*/
static inline void isci_request_free(
struct isci_host *isci_host,
struct isci_request *isci_request)
{
BUG_ON(isci_request == NULL);
/* release the dma memory if we fail. */
dma_pool_free(isci_host->dma_pool, isci_request,
isci_request->request_daddr);
}
/* #define ISCI_REQUEST_VALIDATE_ACCESS
*/
#ifdef ISCI_REQUEST_VALIDATE_ACCESS
static inline
struct sas_task *isci_request_access_task(struct isci_request *isci_request)
{
BUG_ON(isci_request->ttype != io_task);
return isci_request->ttype_ptr.io_task_ptr;
}
static inline
struct isci_tmf *isci_request_access_tmf(struct isci_request *isci_request)
{
BUG_ON(isci_request->ttype != tmf_task);
return isci_request->ttype_ptr.tmf_task_ptr;
}
#else /* not ISCI_REQUEST_VALIDATE_ACCESS */
#define isci_request_access_task(RequestPtr) \
((RequestPtr)->ttype_ptr.io_task_ptr)
#define isci_request_access_tmf(RequestPtr) \
((RequestPtr)->ttype_ptr.tmf_task_ptr)
#endif /* not ISCI_REQUEST_VALIDATE_ACCESS */
int isci_request_alloc_tmf(
struct isci_host *isci_host,
struct isci_tmf *isci_tmf,
struct isci_request **isci_request,
struct isci_remote_device *isci_device,
gfp_t gfp_flags);
int isci_request_execute(
struct isci_host *isci_host,
struct sas_task *task,
struct isci_request **request,
gfp_t gfp_flags);
/**
* isci_request_unmap_sgl() - This function unmaps the DMA address of a given
* sgl
* @request: This parameter points to the isci_request object
* @*pdev: This Parameter is the pci_device struct for the controller
*
*/
static inline void isci_request_unmap_sgl(
struct isci_request *request,
struct pci_dev *pdev)
{
struct sas_task *task = isci_request_access_task(request);
dev_dbg(&request->isci_host->pdev->dev,
"%s: request = %p, task = %p,\n"
"task->data_dir = %d, is_sata = %d\n ",
__func__,
request,
task,
task->data_dir,
sas_protocol_ata(task->task_proto));
if ((task->data_dir != PCI_DMA_NONE) &&
!sas_protocol_ata(task->task_proto)) {
if (task->num_scatter == 0)
/* 0 indicates a single dma address */
dma_unmap_single(
&pdev->dev,
request->zero_scatter_daddr,
task->total_xfer_len,
task->data_dir
);
else /* unmap the sgl dma addresses */
dma_unmap_sg(
&pdev->dev,
task->scatter,
request->num_sg_entries,
task->data_dir
);
}
}
void isci_request_io_request_complete(
struct isci_host *isci_host,
struct isci_request *request,
enum sci_io_status completion_status);
u32 isci_request_io_request_get_transfer_length(
struct isci_request *request);
SCI_IO_REQUEST_DATA_DIRECTION isci_request_io_request_get_data_direction(
struct isci_request *request);
/**
* isci_request_io_request_get_next_sge() - This function is called by the sci
* core to retrieve the next sge for a given request.
* @request: This parameter is the isci_request object.
* @current_sge_address: This parameter is the last sge retrieved by the sci
* core for this request.
*
* pointer to the next sge for specified request.
*/
static inline void *isci_request_io_request_get_next_sge(
struct isci_request *request,
void *current_sge_address)
{
struct sas_task *task = isci_request_access_task(request);
void *ret = NULL;
dev_dbg(&request->isci_host->pdev->dev,
"%s: request = %p, "
"current_sge_address = %p, "
"num_scatter = %d\n",
__func__,
request,
current_sge_address,
task->num_scatter);
if (!current_sge_address) /* First time through.. */
ret = task->scatter; /* always task->scatter */
else if (task->num_scatter == 0) /* Next element, if num_scatter == 0 */
ret = NULL; /* there is only one element. */
else
ret = sg_next(current_sge_address); /* sg_next returns NULL
* for the last element
*/
dev_dbg(&request->isci_host->pdev->dev,
"%s: next sge address = %p\n",
__func__,
ret);
return ret;
}
dma_addr_t isci_request_sge_get_address_field(
struct isci_request *request,
void *sge_address);
u32 isci_request_sge_get_length_field(
struct isci_request *request,
void *sge_address);
void *isci_request_ssp_io_request_get_cdb_address(
struct isci_request *request);
u32 isci_request_ssp_io_request_get_cdb_length(
struct isci_request *request);
u32 isci_request_ssp_io_request_get_lun(
struct isci_request *request);
u32 isci_request_ssp_io_request_get_task_attribute(
struct isci_request *request);
u32 isci_request_ssp_io_request_get_command_priority(
struct isci_request *request);
void isci_terminate_pending_requests(
struct isci_host *isci_host,
struct isci_remote_device *isci_device,
enum isci_request_status new_request_state);
#endif /* !defined(_ISCI_REQUEST_H_) */

356
drivers/scsi/isci/sata.c Normal file
View File

@ -0,0 +1,356 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "isci.h"
#include "scic_remote_device.h"
#include "scic_sds_remote_device.h"
#include "scic_io_request.h"
#include "scic_task_request.h"
#include "task.h"
#include "request.h"
#include "sata.h"
#include "intel_sat.h"
#include "intel_ata.h"
static u8 isci_sata_get_management_task_protocol(struct isci_tmf *tmf);
/**
* isci_sata_task_to_fis_copy() - This function gets the host_to_dev_fis from
* the core and copies the fis from the task into it.
* @task: This parameter is a pointer to the task struct from libsas.
*
* pointer to the host_to_dev_fis from the core request object.
*/
struct host_to_dev_fis *isci_sata_task_to_fis_copy(struct sas_task *task)
{
struct isci_request *request = task->lldd_task;
struct host_to_dev_fis *register_fis =
scic_stp_io_request_get_h2d_reg_address(
request->sci_request_handle
);
memcpy(
(u8 *)register_fis,
(u8 *)&task->ata_task.fis,
sizeof(struct host_to_dev_fis)
);
if (!task->ata_task.device_control_reg_update)
register_fis->flags |= 0x80;
register_fis->flags &= 0xF0;
return register_fis;
}
/**
* isci_sata_is_task_ncq() - This function determines if the given stp task is
* a ncq request.
* @task: This parameter is a pointer to the task struct from libsas.
*
* true if the task is ncq
*/
bool isci_sata_is_task_ncq(struct sas_task *task)
{
struct ata_queued_cmd *qc = task->uldd_task;
bool ret = (qc &&
(qc->tf.command == ATA_CMD_FPDMA_WRITE ||
qc->tf.command == ATA_CMD_FPDMA_READ));
return ret;
}
/**
* isci_sata_set_ncq_tag() - This function sets the ncq tag field in the
* host_to_dev_fis equal to the tag in the queue command in the task.
* @task: This parameter is a pointer to the task struct from libsas.
* @register_fis: This parameter is a pointer to the host_to_dev_fis from the
* core request object.
*
*/
void isci_sata_set_ncq_tag(
struct host_to_dev_fis *register_fis,
struct sas_task *task)
{
struct ata_queued_cmd *qc = task->uldd_task;
struct isci_request *request = task->lldd_task;
register_fis->sector_count = qc->tag << 3;
scic_stp_io_request_set_ncq_tag(request->sci_request_handle, qc->tag);
}
/**
* isci_request_process_stp_response() - This function sets the status and
* response, in the task struct, from the request object for the upper layer
* driver.
* @sas_task: This parameter is the task struct from the upper layer driver.
* @response_buffer: This parameter points to the response of the completed
* request.
*
* none.
*/
void isci_request_process_stp_response(
struct sas_task *task,
void *response_buffer)
{
struct sata_fis_reg_d2h *d2h_reg_fis = (struct sata_fis_reg_d2h *)response_buffer;
struct task_status_struct *ts = &task->task_status;
struct ata_task_resp *resp = (void *)&ts->buf[0];
resp->frame_len = le16_to_cpu(*(__le16 *)(response_buffer + 6));
memcpy(&resp->ending_fis[0], response_buffer + 16, 24);
ts->buf_valid_size = sizeof(*resp);
/**
* If the device fault bit is set in the status register, then
* set the sense data and return.
*/
if (d2h_reg_fis->status & ATA_STATUS_REG_DEVICE_FAULT_BIT)
ts->stat = SAS_PROTO_RESPONSE;
else
ts->stat = SAM_STAT_GOOD;
ts->resp = SAS_TASK_COMPLETE;
}
/**
* isci_sata_get_sat_protocol() - retrieve the sat protocol for the request
* @isci_request: ata request
*
* Note: temporary implementation until expert mode removes the callback
*
*/
u8 isci_sata_get_sat_protocol(struct isci_request *isci_request)
{
struct sas_task *task;
struct domain_device *dev;
dev_dbg(&isci_request->isci_host->pdev->dev,
"%s: isci_request = %p, ttype = %d\n",
__func__, isci_request, isci_request->ttype);
if (tmf_task == isci_request->ttype) {
struct isci_tmf *tmf = isci_request_access_tmf(isci_request);
return isci_sata_get_management_task_protocol(tmf);
}
task = isci_request_access_task(isci_request);
dev = task->dev;
if (!sas_protocol_ata(task->task_proto)) {
WARN(1, "unhandled task protocol\n");
return SAT_PROTOCOL_NON_DATA;
}
if (task->data_dir == DMA_NONE)
return SAT_PROTOCOL_NON_DATA;
/* the "_IN" protocol types are equivalent to their "_OUT"
* analogs as far as the core is concerned
*/
if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) {
if (task->ata_task.dma_xfer)
return SAT_PROTOCOL_PACKET_DMA_DATA_IN;
else
return SAT_PROTOCOL_PACKET_PIO_DATA_IN;
}
if (task->ata_task.use_ncq)
return SAT_PROTOCOL_FPDMA;
if (task->ata_task.dma_xfer)
return SAT_PROTOCOL_UDMA_DATA_IN;
else
return SAT_PROTOCOL_PIO_DATA_IN;
}
static u8 isci_sata_get_management_task_protocol(
struct isci_tmf *tmf)
{
u8 ret = 0;
pr_warn("tmf = %p, func = %d\n", tmf, tmf->tmf_code);
if ((tmf->tmf_code == isci_tmf_sata_srst_high) ||
(tmf->tmf_code == isci_tmf_sata_srst_low)) {
pr_warn("%s: tmf->tmf_code == TMF_LU_RESET\n", __func__);
ret = SAT_PROTOCOL_SOFT_RESET;
}
return ret;
}
enum sci_status isci_sata_management_task_request_build(
struct isci_request *isci_request)
{
struct isci_tmf *isci_tmf;
enum sci_status status;
if (tmf_task != isci_request->ttype)
return SCI_FAILURE;
isci_tmf = isci_request_access_tmf(isci_request);
switch (isci_tmf->tmf_code) {
case isci_tmf_sata_srst_high:
case isci_tmf_sata_srst_low:
{
struct host_to_dev_fis *register_fis =
scic_stp_io_request_get_h2d_reg_address(
isci_request->sci_request_handle
);
memset(register_fis, 0, sizeof(*register_fis));
register_fis->fis_type = 0x27;
register_fis->flags &= ~0x80;
register_fis->flags &= 0xF0;
if (isci_tmf->tmf_code == isci_tmf_sata_srst_high)
register_fis->control |= ATA_SRST;
else
register_fis->control &= ~ATA_SRST;
break;
}
/* other management commnd go here... */
default:
return SCI_FAILURE;
}
/* core builds the protocol specific request
* based on the h2d fis.
*/
status = scic_task_request_construct_sata(
isci_request->sci_request_handle
);
return status;
}
/**
* isci_task_send_lu_reset_sata() - This function is called by of the SAS
* Domain Template functions. This is one of the Task Management functoins
* called by libsas, to reset the given SAS lun. Note the assumption that
* while this call is executing, no I/O will be sent by the host to the
* device.
* @lun: This parameter specifies the lun to be reset.
*
* status, zero indicates success.
*/
int isci_task_send_lu_reset_sata(
struct isci_host *isci_host,
struct isci_remote_device *isci_device,
u8 *lun)
{
struct isci_tmf tmf;
int ret = TMF_RESP_FUNC_FAILED;
unsigned long flags;
/* Send the initial SRST to the target */
#define ISCI_SRST_TIMEOUT_MS 20 /* 20 ms timeout. */
isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_high,
NULL, NULL
);
ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS);
if (ret != TMF_RESP_FUNC_COMPLETE) {
dev_warn(&isci_host->pdev->dev,
"%s: Assert SRST failed (%p) = %x",
__func__,
isci_device,
ret);
/* Return the failure so that the LUN reset is escalated
* to a target reset.
*/
goto out;
}
/* Leave SRST high for a bit. */
#define ISCI_SRST_ASSERT_DELAY 100 /* usecs */
scic_cb_stall_execution(ISCI_SRST_ASSERT_DELAY);
/* Deassert SRST. */
isci_task_build_tmf(&tmf, isci_device, isci_tmf_sata_srst_low,
NULL, NULL
);
ret = isci_task_execute_tmf(isci_host, &tmf, ISCI_SRST_TIMEOUT_MS);
if (ret == TMF_RESP_FUNC_COMPLETE)
dev_dbg(&isci_host->pdev->dev,
"%s: SATA LUN reset passed (%p)\n",
__func__,
isci_device);
else
dev_warn(&isci_host->pdev->dev,
"%s: Deassert SRST failed (%p)=%x\n",
__func__,
isci_device,
ret);
out:
spin_lock_irqsave(&isci_host->scic_lock, flags);
/* Resume the device. */
scic_sds_remote_device_resume(isci_device->sci_device_handle);
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
return ret;
}

83
drivers/scsi/isci/sata.h Normal file
View File

@ -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.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "intel_sat.h"
struct host_to_dev_fis *isci_sata_task_to_fis_copy(
struct sas_task *task);
bool isci_sata_is_task_ncq(
struct sas_task *task);
void isci_sata_set_ncq_tag(
struct host_to_dev_fis *register_fis,
struct sas_task *task);
void isci_request_process_stp_response(
struct sas_task *task,
void *response_buffer);
u8 isci_sata_get_sat_protocol(
struct isci_request *isci_request);
enum sci_status isci_sata_management_task_request_build(
struct isci_request *isci_request);
int isci_task_send_lu_reset_sata(
struct isci_host *isci_host,
struct isci_remote_device *isci_device,
u8 *lun);

View File

@ -0,0 +1,112 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SCI_ENVIRONMENT_H_
#define _SCI_ENVIRONMENT_H_
#include "isci.h"
struct scic_sds_controller;
struct scic_sds_phy;
struct scic_sds_port;
struct scic_sds_remote_device;
static inline struct device *scic_to_dev(struct scic_sds_controller *scic)
{
struct isci_host *isci_host = sci_object_get_association(scic);
return &isci_host->pdev->dev;
}
static inline struct device *sciphy_to_dev(struct scic_sds_phy *sci_phy)
{
struct isci_phy *iphy = sci_object_get_association(sci_phy);
if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)
return NULL;
return &iphy->isci_port->isci_host->pdev->dev;
}
static inline struct device *sciport_to_dev(struct scic_sds_port *sci_port)
{
struct isci_port *iport = sci_object_get_association(sci_port);
if (!iport || !iport->isci_host)
return NULL;
return &iport->isci_host->pdev->dev;
}
static inline struct device *scirdev_to_dev(struct scic_sds_remote_device *sci_dev)
{
struct isci_remote_device *idev = sci_object_get_association(sci_dev);
if (!idev || !idev->isci_port || !idev->isci_port->isci_host)
return NULL;
return &idev->isci_port->isci_host->pdev->dev;
}
enum {
ISCI_SI_REVA0,
ISCI_SI_REVA2,
ISCI_SI_REVB0,
};
extern int isci_si_rev;
#endif

1691
drivers/scsi/isci/task.c Normal file

File diff suppressed because it is too large Load Diff

368
drivers/scsi/isci/task.h Normal file
View File

@ -0,0 +1,368 @@
/*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* BSD LICENSE
*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if !defined(_ISCI_TASK_H_)
#define _ISCI_TASK_H_
struct isci_request;
struct isci_host;
/**
* enum isci_tmf_cb_state - This enum defines the possible states in which the
* TMF callback function is invoked during the TMF execution process.
*
*
*/
enum isci_tmf_cb_state {
isci_tmf_init_state = 0,
isci_tmf_started,
isci_tmf_timed_out
};
/**
* enum isci_tmf_function_codes - This enum defines the possible preparations
* of task management requests.
*
*
*/
enum isci_tmf_function_codes {
isci_tmf_func_none = 0,
isci_tmf_ssp_task_abort = TMF_ABORT_TASK,
isci_tmf_ssp_lun_reset = TMF_LU_RESET,
isci_tmf_sata_srst_high = TMF_LU_RESET + 0x100, /* Non SCSI */
isci_tmf_sata_srst_low = TMF_LU_RESET + 0x101 /* Non SCSI */
};
/**
* struct isci_tmf - This class represents the task management object which
* acts as an interface to libsas for processing task management requests
*
*
*/
struct isci_tmf {
struct completion *complete;
enum sas_protocol proto;
union {
struct sci_ssp_response_iu resp_iu;
struct dev_to_host_fis d2h_fis;
} resp;
unsigned char lun[8];
u16 io_tag;
struct isci_remote_device *device;
enum isci_tmf_function_codes tmf_code;
int status;
struct isci_timer *timeout_timer;
/* The optional callback function allows the user process to
* track the TMF transmit / timeout conditions.
*/
void (*cb_state_func)(
enum isci_tmf_cb_state,
struct isci_tmf *, void *);
void *cb_data;
};
static inline void isci_print_tmf(
struct isci_tmf *tmf)
{
if (SAS_PROTOCOL_SATA == tmf->proto)
dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
"%s: status = %x\n"
"tmf->resp.d2h_fis.status = %x\n"
"tmf->resp.d2h_fis.error = %x\n",
__func__,
tmf->status,
tmf->resp.d2h_fis.status,
tmf->resp.d2h_fis.error);
else
dev_dbg(&tmf->device->isci_port->isci_host->pdev->dev,
"%s: status = %x\n"
"tmf->resp.resp_iu.data_present = %x\n"
"tmf->resp.resp_iu.status = %x\n"
"tmf->resp.resp_iu.data_length = %x\n"
"tmf->resp.resp_iu.data[0] = %x\n"
"tmf->resp.resp_iu.data[1] = %x\n"
"tmf->resp.resp_iu.data[2] = %x\n"
"tmf->resp.resp_iu.data[3] = %x\n",
__func__,
tmf->status,
tmf->resp.resp_iu.data_present,
tmf->resp.resp_iu.status,
(tmf->resp.resp_iu.response_data_length[0] << 24) +
(tmf->resp.resp_iu.response_data_length[1] << 16) +
(tmf->resp.resp_iu.response_data_length[2] << 8) +
tmf->resp.resp_iu.response_data_length[3],
tmf->resp.resp_iu.data[0],
tmf->resp.resp_iu.data[1],
tmf->resp.resp_iu.data[2],
tmf->resp.resp_iu.data[3]);
}
int isci_task_execute_task(
struct sas_task *task,
int num,
gfp_t gfp_flags);
int isci_task_abort_task(
struct sas_task *task);
int isci_task_abort_task_set(
struct domain_device *d_device,
u8 *lun);
int isci_task_clear_aca(
struct domain_device *d_device,
u8 *lun);
int isci_task_clear_task_set(
struct domain_device *d_device,
u8 *lun);
int isci_task_query_task(
struct sas_task *task);
int isci_task_lu_reset(
struct domain_device *d_device,
u8 *lun);
int isci_task_clear_nexus_port(
struct asd_sas_port *port);
int isci_task_clear_nexus_ha(
struct sas_ha_struct *ha);
int isci_task_I_T_nexus_reset(
struct domain_device *d_device);
void isci_task_request_complete(
struct isci_host *isci_host,
struct isci_request *request,
enum sci_task_status completion_status);
u16 isci_task_ssp_request_get_io_tag_to_manage(
struct isci_request *request);
u8 isci_task_ssp_request_get_function(
struct isci_request *request);
u32 isci_task_ssp_request_get_lun(
struct isci_request *request);
void *isci_task_ssp_request_get_response_data_address(
struct isci_request *request);
u32 isci_task_ssp_request_get_response_data_length(
struct isci_request *request);
int isci_queuecommand(
struct scsi_cmnd *scsi_cmd,
void (*donefunc)(struct scsi_cmnd *));
int isci_bus_reset_handler(struct scsi_cmnd *cmd);
void isci_task_build_tmf(
struct isci_tmf *tmf,
struct isci_remote_device *isci_device,
enum isci_tmf_function_codes code,
void (*tmf_sent_cb)(
enum isci_tmf_cb_state,
struct isci_tmf *, void *),
void *cb_data);
int isci_task_execute_tmf(
struct isci_host *isci_host,
struct isci_tmf *tmf,
unsigned long timeout_ms);
/**
* enum isci_completion_selection - This enum defines the possible actions to
* take with respect to a given request's notification back to libsas.
*
*
*/
enum isci_completion_selection {
isci_perform_normal_io_completion, /* Normal notify (task_done) */
isci_perform_aborted_io_completion, /* No notification. */
isci_perform_error_io_completion /* Use sas_task_abort */
};
static inline void isci_set_task_doneflags(
struct sas_task *task)
{
/* Since no futher action will be taken on this task,
* make sure to mark it complete from the lldd perspective.
*/
task->task_state_flags |= SAS_TASK_STATE_DONE;
task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
task->task_state_flags &= ~SAS_TASK_STATE_PENDING;
}
/**
* isci_task_all_done() - This function clears the task bits to indicate the
* LLDD is done with the task.
*
*
*/
static inline void isci_task_all_done(
struct sas_task *task)
{
unsigned long flags;
/* Since no futher action will be taken on this task,
* make sure to mark it complete from the lldd perspective.
*/
spin_lock_irqsave(&task->task_state_lock, flags);
isci_set_task_doneflags(task);
spin_unlock_irqrestore(&task->task_state_lock, flags);
}
/**
* isci_task_set_completion_status() - This function sets the completion status
* for the request.
* @task: This parameter is the completed request.
* @response: This parameter is the response code for the completed task.
* @status: This parameter is the status code for the completed task.
*
* none.
*/
static inline void isci_task_set_completion_status(
struct sas_task *task,
enum service_response response,
enum exec_status status,
enum isci_completion_selection task_notification_selection)
{
unsigned long flags;
spin_lock_irqsave(&task->task_state_lock, flags);
task->task_status.resp = response;
task->task_status.stat = status;
/* Don't set DONE (or clear AT_INITIATOR) for any task going into the
* error path, because the EH interprets that as a handled error condition.
* Also don't take action if there is a reset pending.
*/
if ((task_notification_selection != isci_perform_error_io_completion)
&& !(task->task_state_flags & SAS_TASK_NEED_DEV_RESET))
isci_set_task_doneflags(task);
spin_unlock_irqrestore(&task->task_state_lock, flags);
}
/**
* isci_task_complete_for_upper_layer() - This function completes the request
* to the upper layer driver.
* @host: This parameter is a pointer to the host on which the the request
* should be queued (either as an error or success).
* @request: This parameter is the completed request.
* @response: This parameter is the response code for the completed task.
* @status: This parameter is the status code for the completed task.
*
* none.
*/
static inline void isci_task_complete_for_upper_layer(
struct sas_task *task,
enum service_response response,
enum exec_status status,
enum isci_completion_selection task_notification_selection)
{
isci_task_set_completion_status(task, response, status,
task_notification_selection);
/* Tasks aborted specifically by a call to the lldd_abort_task
* function should not be completed to the host in the regular path.
*/
switch (task_notification_selection) {
case isci_perform_normal_io_completion:
/* Normal notification (task_done) */
dev_dbg(task->dev->port->ha->dev,
"%s: Normal - task = %p, response=%d, status=%d\n",
__func__, task, response, status);
task->task_done(task);
task->lldd_task = NULL;
break;
case isci_perform_aborted_io_completion:
/* No notification because this request is already in the
* abort path.
*/
dev_warn(task->dev->port->ha->dev,
"%s: Aborted - task = %p, response=%d, status=%d\n",
__func__, task, response, status);
break;
case isci_perform_error_io_completion:
/* Use sas_task_abort */
dev_warn(task->dev->port->ha->dev,
"%s: Error - task = %p, response=%d, status=%d\n",
__func__, task, response, status);
sas_task_abort(task);
break;
default:
dev_warn(task->dev->port->ha->dev,
"%s: isci task notification default case!",
__func__);
sas_task_abort(task);
break;
}
}
#endif /* !defined(_SCI_TASK_H_) */

Some files were not shown because too many files have changed in this diff Show More