From mboxrd@z Thu Jan 1 00:00:00 1970 From: Luben Tuikov Subject: [ANNOUNCE] Adaptec SAS/SATA device driver [20/27] Date: Thu, 17 Feb 2005 12:37:22 -0500 Message-ID: <4214D652.9030300@adaptec.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Received: from magic.adaptec.com ([216.52.22.17]:32146 "EHLO magic.adaptec.com") by vger.kernel.org with ESMTP id S262336AbVBQRha (ORCPT ); Thu, 17 Feb 2005 12:37:30 -0500 Received: from redfish.adaptec.com (redfish.adaptec.com [162.62.50.11]) by magic.adaptec.com (8.11.6/8.11.6) with ESMTP id j1HHbPr31490 for ; Thu, 17 Feb 2005 09:37:25 -0800 Received: from rtpe2k01.adaptec.com (rtpe2k01.adaptec.com [10.110.12.40]) by redfish.adaptec.com (8.11.6/8.11.6) with ESMTP id j1HHbPb21452 for ; Thu, 17 Feb 2005 09:37:25 -0800 Sender: linux-scsi-owner@vger.kernel.org List-Id: linux-scsi@vger.kernel.org To: SCSI Mailing List SAS header file definitions. diff -Nru a/drivers/scsi/adp94xx/adp94xx_sas.h b/drivers/scsi/adp94xx/adp94xx_sas.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/scsi/adp94xx/adp94xx_sas.h 2005-02-16 16:08:12 -05:00 @@ -0,0 +1,1101 @@ +/* + * Adaptec ADP94xx SAS HBA device driver for Linux. + * Serial Attached SCSI (SAS) definitions. + * + * Written by : David Chaw + * + * Copyright (c) 2004 Adaptec Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * $Id: //depot/razor/linux/src/adp94xx_sas.h#50 $ + * + */ + +#ifndef ADP94XX_SAS_H +#define ADP94XX_SAS_H + + +/* + * Connection Rate. + */ +#define SAS_60GBPS_RATE 600000000 +#define SAS_30GBPS_RATE 300000000 +#define SAS_15GBPS_RATE 150000000 +#define SAS_INVALID_RATE 0xFFFFFFFF + +/* Connection Rate to be used in OPEN address frame. */ +#define SAS_RATE_30GBPS 0x09 +#define SAS_RATE_15GBPS 0x08 + +#define SAS_ADDR_LEN 8 +#define HASHED_SAS_ADDR_LEN 3 + +/* + * SAS SCB site common definitions. + */ +#define SCB_SITE_Q_NEXT 0x0 +#define SCB_SITE_FLAGS 0x49 + +/* + * SG Element Format (16 bytes). + */ +struct sg_element { + uint64_t bus_address; + /* + * length and next_sg_offset + * are unused for link_element + * S/G entries. These entries + * just serve as a pointer to + * the next S/G sublist to process. + */ + uint32_t length; + uint8_t res_1[2]; + uint8_t next_sg_offset; +#define SG_NEXT_OFFSET 0x20 + uint8_t flags; +#define SG_EOS 0x80 +#define SG_EOL 0x40 +#define SG_NO_DATA (SG_EOS|SG_EOL) +#define SG_DS_MASK 0x30 +#define SG_DS_ONCHIP 0x10 +#define SG_DS_OFFCHIP 0x00 +} __packed; + + +/* + * Protocol type definitions. + */ +#define PROTOCOL_TYPE_SSP (1U << 4) +#define PROTOCOL_TYPE_SATA (1U << 5) +#define PROTOCOL_TYPE_SMP (0U << 6) +#define PROTOCOL_TYPE_STP PROTOCOL_TYPE_SATA +#define PROTOCOL_TYPE_MASK 0x70 + +/* + * Data Direction definitions. + */ +#define DATA_DIR_NO_XFER (0U << 1) +#define DATA_DIR_INBOUND (1U << 0) +#define DATA_DIR_OUTBOUND (1U << 1) +#define DATA_DIR_UNSPECIFIED (3U << 0) + +/* + * Task Management Functions. + */ +#define ABORT_TASK_TMF 0x01 +#define ABORT_TASK_SET_TMF 0x02 +#define CLEAR_TASK_SET_TMF 0x04 +#define LOGICAL_UNIT_RESET_TMF 0x08 +#define CLEAR_ACA_TMF 0x40 +#define QUERY_TASK_TMF 0x80 + +/* + * NOTE: Unless specified, all fields should be filled with Little Endian + * format. + */ + +/* SCB Common Header (11 bytes) */ +struct hscb_header { + uint64_t next_hscb_busaddr; + uint16_t index; + uint8_t opcode; +} __packed; + +/* SAS Frame Header (24 bytes) - All fields are in "wire" format (Big Endian) */ +struct asd_sas_header { + uint8_t frame_type; +#define ID_ADDR_FRAME 0x00 +#define OPEN_ADDR_FRAME 0x01 +#define XFER_RDY_FRAME 0x05 +#define COMMAND_FRAME 0x06 +#define RESPONSE_FRAME 0x07 +#define TASK_FRAME 0x16 + + uint8_t hashed_dest_sasaddr[HASHED_SAS_ADDR_LEN]; + uint8_t res; + uint8_t hashed_src_sasaddr[HASHED_SAS_ADDR_LEN]; + uint8_t res1[2]; + uint8_t retransmit; + uint8_t num_fill_bytes; + uint8_t res2[4]; + uint16_t tag; + uint16_t target_port_xfer_tag; + uint32_t data_offset; +} __packed; + +/* SAS SSP Task Information Unit (28 bytes) */ +struct asd_ssp_task_iu { + uint8_t lun[8]; + uint16_t res1; + uint8_t tmf; + uint8_t res2; + uint16_t tag_to_manage; + uint8_t res3[14]; +} __packed; + +/* SAS SSP Response Information Unit (24 byts + response data + sense data) */ +struct resp_data_iu { + uint8_t res[3]; + uint8_t resp_code; +#define TMF_COMPLETE 0x00 +#define INVALID_FRAME 0x02 +#define TMF_NOT_SUPPORTED 0x04 +#define TMF_FAILED 0x05 +#define TMF_SUCCEEDED 0x08 +#define INVALID_LUN 0x09 +} __packed; + +struct ssp_resp_iu { + uint8_t res_1[10]; + uint8_t datapres; +#define SSP_RIU_DATAPRES_MASK 0x3 +#define SSP_RIU_DATAPRES_NONE 0x0 +#define SSP_RIU_DATAPRES_RESP 0x1 +#define SSP_RIU_DATAPRES_SENSE 0x2 +#define SSP_RIU_DATAPRES(riu) \ + ((riu)->datapres & SSP_RIU_DATAPRES_MASK) + + uint8_t status; + uint8_t res_2[4]; + uint8_t sense_len[4]; + uint8_t response_len[4]; + uint8_t data[0]; /* Place Holder */ +}; + +struct ssp_resp_frame { + struct asd_sas_header sas_header; + struct ssp_resp_iu riu; +} __packed; +#define SSP_RIU_DATA_OFFSET(riu) \ + (offsetof(struct asd_ssp_response_iu, data)) +#define SSP_RIU_RESPONSE_CODE(riu) (scsi_4btoul((riu)->data) & 0xFF) + +/* Retry count used by sequencer for SSP, ATA, and ATAPI task. */ +#define TASK_RETRY_CNT 3 + +/* Suspend data transmission, valid for ABORT TASK and INITIATE SSP TMF. */ +#define SUSPEND_DATA (1U << 2) + +/* + * Initiate SSP TASK to a SAS target. + */ +#define SCB_INITIATE_SSP_TASK 0x00 +#define SCB_EMBEDDED_CDB_SIZE 16 +struct asd_ssp_task_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint32_t xfer_len; + struct asd_sas_header sas_header; + uint8_t lun[8]; + uint8_t res1; + uint8_t task_attr; + uint8_t task_mgmt_func; + uint8_t addl_cdb_len; + uint8_t cdb[SCB_EMBEDDED_CDB_SIZE]; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t data_dir_flags; + uint8_t res2; + uint8_t retry_cnt; + uint8_t res3[5]; + + /* Embedded SG Elements (0-2). Each SG Element is 16 bytes. */ + struct sg_element sg_elements[3]; +} __packed; + +#define LAST_SSP_HSCB_FIELD res3[0] + +/* + * Initiate Long SSP Task to a SAS target. + */ +#define SCB_INITIATE_LONG_SSP_TASK 0x01 +struct asd_ssp_long_task_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint32_t xfer_len; + struct asd_sas_header sas_header; + uint8_t lun[8]; + uint8_t res1; + uint8_t task_attr; + uint8_t res2; + uint8_t addl_cdb_len; + uint64_t long_cdb_busaddr; + uint32_t long_cdb_size; + uint8_t res3[3]; + uint8_t long_cdb_ds; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t data_dir_flags; + uint8_t res4; + uint8_t retry_cnt; + uint8_t res5[5]; + struct sg_element sg_elements[3]; +} __packed; + +/* + * Initiate Abort for an SCB previously sent to CSEQ. + * This SCB_ABORT_TASK shall be used only to abort an SCB with an opcode of + * - SCB_INITIATE_SSP_TASK + * - SCB_INITIATE_LONG_SSP_TASK + * - SCB_INITIATE_BIDIR_SSP_TASK + * - SCB_INITIATE_SMP_TASK + * - SCB_INITIATE_ATA_TASK + * - SCB_INITIATE_ATAPI_TASK + */ +#define SCB_ABORT_TASK 0x03 +struct asd_abort_task_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint32_t res1; + struct asd_sas_header sas_header; + + /* + * SSP Task IU field shall ony be valid when aborting an SCB with + * PROTOCOL field of SSP. + */ + struct asd_ssp_task_iu task_iu; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t suspend_data; + uint8_t res2; + uint8_t retry_cnt; + uint8_t res3[5]; + uint16_t tc_to_abort; + uint8_t res4[46]; +} __packed; + +/* + * Initiate an SSP TASK information unit for a LOGICAL UNIT RESET, + * ABORT TASK SET, CLEAR TASK SET, or CLEAR ACA task management function. + */ +#define SCB_INITIATE_SSP_TMF 0x04 +struct asd_ssp_tmf_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint32_t res1; + struct asd_sas_header sas_header; + struct asd_ssp_task_iu task_iu; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t suspend_data; + uint8_t res2; + uint8_t retry_cnt; + uint8_t res3[5]; + uint8_t res4[48]; +} __packed; + +/* + * Initiate Query SSP Task. + */ +#define SCB_QUERY_SSP_TASK 0x08 +struct asd_query_ssp_task_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint32_t res1; + struct asd_sas_header sas_header; + struct asd_ssp_task_iu task_iu; + uint16_t sister_scb; + uint16_t conn_handle; + uint16_t res2; + uint8_t retry_cnt; + uint8_t res3[5]; + uint16_t tc_to_query; + uint8_t res4[46]; +} __packed; + +/* + * Initiate ATA Task to a SATA target. + */ +#define SCB_INITIATE_ATA_TASK 0x09 +struct asd_ata_task_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint32_t xfer_len; + uint8_t host_to_dev_reg_fis[20]; + uint32_t data_offset; + uint8_t res1[16]; + uint8_t res2[12]; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t ata_flags; +#define CSMI_TASK (1U << 6) +#define DMA_XFER_MODE (1U << 4) +#define UNTAGGED (0U << 3) +#define LEGACY_QUEUING (1U << 3) +#define NATIVE_QUEUING (3U << 2) + + uint8_t res3; + uint8_t retry_cnt; + uint8_t res4; + uint8_t affiliation_policy; /* + * Bit 4 is Set + * Affiliation Policy + * and Bit 5 is STP + * Affiliation Policy. + */ + uint8_t res5[3]; + struct sg_element sg_elements[3]; +} __packed; + +/* + * Initiate ATAPI Task to an ATAPI target. + */ +#define SCB_INITIATE_ATAPI_TASK 0x0A +struct asd_atapi_task_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint32_t xfer_len; + uint8_t host_to_dev_reg_fis[20];/* Packet Command */ + uint32_t data_offset; + uint8_t atapi_packet[SCB_EMBEDDED_CDB_SIZE]; + uint8_t res1[12]; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t ata_flags; /* + * ATA flags definition + * is similar to + * INITIATE_ATA_TASK + * except bits 2 and 3 + * (QUEUEING TYPE) + * should be set 0 + * (UNTAGGED). + */ + uint8_t res2; + uint8_t retry_cnt; + uint8_t res3; + uint8_t affiliation_policy; /* + * Bit 4 is Set + * Affiliation Policy + * and Bit 5 is STP + * Affiliation Policy. + */ + uint8_t res4[3]; + struct sg_element sg_elements[3]; +} __packed; + +/* + * Initiate an ATA device control function (e.g. software reset). + */ +#define SCB_CONTROL_ATA_DEVICE 0x0B +struct asd_control_ata_dev_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint8_t res1[4]; + uint8_t host_to_dev_reg_fis[20]; + uint8_t res2[32]; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t ata_flags; /* Must be set to 0. */ + uint8_t res3[55]; +} __packed; + +/* + * Initiate an SMP task to an expander. + */ +#define SCB_INITIATE_SMP_TASK 0x0C +struct asd_smp_task_hscb { + struct hscb_header header; + uint8_t protocol_conn_rate; + uint8_t res1[40]; + uint64_t smp_req_busaddr; + uint32_t smp_req_size; + uint8_t res2[3]; + uint8_t smp_req_ds; + uint16_t sister_scb; + uint16_t conn_handle; + uint8_t res3[8]; + uint64_t smp_resp_busaddr; + uint32_t smp_resp_size; + uint8_t res4[3]; + uint8_t smp_resp_ds; + uint8_t res5[32]; +} __packed; + +/* + * Control the operation of a PHY. + */ +#define SCB_CONTROL_PHY 0x80 +struct asd_control_phy_hscb { + struct hscb_header header; + uint8_t phy_id; + uint8_t sub_func; +#define DISABLE_PHY 0x00 +#define ENABLE_PHY 0x01 +#define RELEASE_SPINUP_HOLD 0x02 +#define ENABLE_PHY_NO_SAS_OOB 0x03 +#define ENABLE_PHY_NO_SATA_OOB 0x04 +#define PHY_NO_OP 0x05 +#define EXECUTE_HARD_RESET 0x81 + + /* + * OOB FUNCTION_MASK, SPEED_MASK, and HOT_PLUG_DELAY only valid for + * sub-functions ENABLE_PHY and EXECUTE_HARD_RESET. + */ + uint8_t func_mask; + uint8_t speed_mask; + uint8_t hot_plug_delay; + uint8_t port_type; +#define SSP_INITIATOR_PORT (1U << 7) +#define STP_INITIATOR_PORT (1U << 6) +#define SMP_INITIATOR_PORT (1U << 5) + + uint8_t ovrd_devpres_timer; + uint32_t devpres_timer_to_const_ovrd; + uint8_t link_reset_retries; + uint8_t res1[47]; + uint16_t conn_handle; + uint8_t res2[56]; +} __packed; + +/* + * Initiate an administrative task to the particular link. + */ +#define SCB_LINK_ADMIN_TASK 0x82 +struct asd_link_admin_hscb { + struct hscb_header header; + uint8_t phy_id; + uint8_t sub_func; +#define GET_LINK_ERR_CNT 0x00 +#define RESET_LINK_ERR_CNT 0x01 +#define EN_NOTIFY_SPINUP_INTS 0x02 + + uint8_t res1[57]; + uint16_t conn_handle; + uint8_t res[56]; +} __packed; + +/* + * Empty Buffer Element format (16 bytes). + */ +struct empty_buf_elem { + uint64_t busaddr; + uint32_t buffer_size; + uint8_t res[3]; + uint8_t elem_valid_ds; +#define ELEM_BUFFER_VALID_MASK 0xC0 +#define ELEM_BUFFER_VALID 0x00 +#define ELEM_BUFFER_INVALID 0xC0 +#define ELEM_BUFFER_VALID_FIELD(ebe) \ + ((ebe)->elem_valid_ds & ELEM_BUFFER_VALID_MASK) +} __packed; + +/* + * Provide Empty Data Buffers for Sequencer. + */ +#define SCB_EMPTY_BUFFER 0xC0 +struct asd_empty_hscb { + struct hscb_header header; + uint8_t num_valid_elems; + uint8_t res1[4]; + struct empty_buf_elem buf_elem[7]; +} __packed; + + +/* + * Initiate a copy between two bus addresses using on-chip DMA engine. + */ +#define SCB_COPY_MEMORY 0xC3 +struct asd_copy_mem_hscb { + struct hscb_header header; + uint8_t res1; + uint16_t xfer_len; + uint8_t res2[2]; + uint64_t src_bus_addr; + uint8_t src_sg_flags; + uint8_t res3[45]; + uint16_t conn_handle; + uint8_t res4[8]; + uint64_t dst_bus_addr; + uint8_t dst_sg_flags; +} __packed; + +/* + * Initiate a request that a set of transactions pending for a specified nexus + * be retun to driver via DL entries and the SCB sites (and tag number) be + * returned to the free list of SCBs. + */ +#define SCB_CLEAR_NEXUS 0xC4 +struct asd_clear_nexus_hscb { + struct hscb_header header; + uint8_t nexus_ind; +#define CLR_NXS_ADAPTER 0 +#define CLR_NXS_I_OR_T 1 +#define CLR_NXS_IT_OR_TI 2 +#define CLR_NXS_I_T_L 3 +#define CLR_NXS_I_T_L_Q_TAG 4 +#define CLR_NXS_I_T_L_Q_TC 5 +#define CLR_NXS_I_T_L_Q_STAG 6 + + uint8_t res1[4]; + uint8_t queue_ind; +#define NOT_IN_Q (1U << 0) +#define EXEC_Q (1U << 1) +#define SEND_Q (1U << 2) +#define RESUME_TX (1U << 6) +#define SUSPEND_TX (1U << 7) + + uint8_t res2[3]; + uint8_t conn_mask_to_clr; + uint8_t res3[3]; + uint8_t res4[16]; + uint8_t lun_to_clr[8]; + uint8_t res5[4]; + uint16_t tag_to_clr; + uint8_t res6[16]; + uint16_t conn_handle_to_clr; + uint8_t res7[8]; + uint16_t tc_to_clr; + uint16_t nexus_ctx; + uint8_t res8[44]; +} __packed; + +/* + * SAS SCB data strucutes. + */ +union hardware_scb { + struct hscb_header header; + struct asd_ssp_task_hscb ssp_task; + struct asd_ssp_long_task_hscb long_ssp_task; + struct asd_abort_task_hscb abort_task; + struct asd_ssp_tmf_hscb ssp_tmf; + struct asd_query_ssp_task_hscb query_ssp_task; + struct asd_ata_task_hscb ata_task; + struct asd_atapi_task_hscb atapi_task; + struct asd_control_ata_dev_hscb control_ata_dev; + struct asd_smp_task_hscb smp_task; + struct asd_control_phy_hscb control_phy; + struct asd_link_admin_hscb link_admin; + struct asd_empty_hscb empty_scb; + struct asd_copy_mem_hscb copy_mem; + struct asd_clear_nexus_hscb clear_nexus; + uint8_t bytes[128]; +} __packed; + + +/* + * Done List Opcode definitions. + * TASK_COMPLETE (TASK_COMP) : Indicates status was received and acknowledged. + * TASK_FAILED (TASK_F) : Indicates an error occured prior to receving an + * an acknowledgement for the command. + * TASK_UNACKED (TASK_UA) : Indicates the command was transmitted to the + * target, but an ACK (R_OK) or NAK (R_ERR) was not + * received. + * TASK_INTERRUPTED (TASK_INT): Indicates an error occured after the command was + * acknowledged. + * TASK_COMPLETE_WITH_RESPONSE: Indicates status was received and acknowledged + * (TASK_COMP_W_RESP) with response. + */ +#define TASK_COMP_WO_ERR 0x00 +#define TASK_COMP_W_UNDERRUN 0x01 +#define TASK_COMP_W_OVERRUN 0x02 +#define TASK_F_W_OPEN_REJECT 0x04 +#define TASK_INT_W_BRK_RCVD 0x05 +#define TASK_INT_W_PROT_ERR 0x06 +#define SSP_TASK_COMP_W_RESP 0x07 +#define TASK_INT_W_PHY_DOWN 0x08 +#define LINK_ADMIN_TASK_COMP_W_RESP 0x0A +#define CSMI_TASK_COMP_WO_ERR 0x0B +#define ATA_TASK_COMP_W_RESP 0x0C +#define TASK_INT_W_NAK_RCVD 0x10 +#define CONTROL_PHY_TASK_COMP 0x11 +#define RESUME_COMPLETE 0x13 +#define TASK_INT_W_ACKNAK_TO 0x14 +#define TASK_F_W_SMPRSP_TO 0x15 +#define TASK_F_W_SMP_XMTRCV_ERR 0x16 +#define TASK_F_W_NAK_RCVD 0x1A +#define TASK_ABORTED_BY_ITNL_EXP 0x1B +#define ATA_TASK_COMP_W_R_ERR_RCVD 0x1C +#define TMF_F_W_TC_NOT_FOUND 0x1D +#define TASK_ABORTED_ON_REQUEST 0x1E +#define TMF_F_W_TAG_NOT_FOUND 0x1F +#define TMF_F_W_TAG_ALREADY_FREE 0x20 +#define TMF_F_W_TAG_ALREADY_DONE 0x21 +#define TMF_F_W_CONN_HNDL_NOT_FOUND 0x22 +#define TASK_CLEARED 0x23 +#define TASK_UA_W_SYNCS_RCVD 0x25 +#define EMPTY_BUFFER_RCVD 0xC0 /* or'ed with EDB element. */ + +/* + * Status block format. + */ + +/* Generic status block format. */ +struct generic_sb { + uint32_t res; +} __packed; + +/* Task Complete Without Error format. */ +struct no_error_sb { + uint16_t cons_idx; /* SCB consumer index.*/ + uint16_t res; +} __packed; + +/* Task Complete With Data UNDERRUN format. */ +struct data_underrun_sb { + uint32_t res_len; /* Residual length. */ +} __packed; + +/* Task Complete With Response format. */ +struct response_sb { + uint16_t empty_scb_tc; + uint8_t empty_buf_len; + uint8_t empty_buf_elem; /* + * The first 3 bits + * represents msb of + * empty_buf_len. + */ +#define EDB_ELEM_MASK 0x70 +#define EDB_ELEM_SHIFT 4 +#define RSP_EDB_ELEM(rsp) \ + (((rsp)->empty_buf_elem & EDB_ELEM_MASK) >> EDB_ELEM_SHIFT) +#define EDB_BUF_LEN_MSB_MASK 0x7 +#define EDB_BUF_LEN_MSB_SHIFT 8 +#define RSP_EDB_BUFLEN(rsp) \ + ((rsp)->empty_buf_len \ + | (((rsp)->empty_buf_elem & EDB_BUF_LEN_MSB_MASK) << EDB_BUF_LEN_MSB_SHIFT)) +} __packed; + +/* Task Failed with Open Reject. */ +struct open_reject_sb { + uint8_t res1; + uint8_t abandon_open; + uint8_t reason; + uint8_t res2; +} __packed; + +/* SSP Response Empty Buffer format. */ +struct ssp_resp_edb { + uint32_t res_len; + + /* + * TAG_TO_CLEAR field shall valid only for an SCB with an + * ABORT TASK SCB, which indicates the value of the + * TAG OF TASK TO BE MANAGED field for the ABORT TASK + * information unit. + */ + uint16_t tag_to_clear; + uint16_t rcvd_frame_len; + uint8_t res[8]; + struct ssp_resp_frame resp_frame; +} __packed; + +/* Get Link Error Counters Empty Buffer format. */ +struct link_err_cnt_edb { + uint32_t inv_dword_cnt; + uint32_t disparity_err_cnt; + uint32_t loss_of_sync_cnt; + uint32_t phy_reset_cnt; +} __packed; + +/* ATA Response Empty Buffer format. */ +struct ata_resp_edb { + uint32_t residual_len; + uint16_t res1; + uint16_t rcvd_frame_len; + uint8_t res2[8]; + uint8_t ending_fis[24]; + uint32_t sstatus; + uint32_t serror; + uint32_t scontrol; + uint32_t sactive; +} __packed; + +/* + * We purposely *do not* pack this union so that an array + * of edbs is aligned on an efficient machine boundary. + * Our only requirement is that the fields within an edb + * be left unpadded. + */ +union edb { + struct ssp_resp_edb ssp_resp; + struct ata_resp_edb ata_resp; + struct link_err_cnt_edb link_err_cnt; + uint8_t bytes[1068]; +}; + +/* Control PHY Task Complete format. */ +struct control_phy_sb { + uint8_t sb_opcode; +#define PHY_RESET_COMPLETED 0x00 + + /* The fields below are only used for PHY_RESET_COMPLETED. */ + uint8_t oob_status; + uint8_t oob_mode; + uint8_t oob_signals; +}; + +/* I_T Nexus Loss Expired format. */ +/* Status Sub-Block format. */ +struct open_timeout_ssb { + uint8_t break_timeout; + uint16_t res; +} __packed; + +struct open_reject_ssb { + uint8_t abandon_retry_open; + uint8_t open_reject_reason; + uint8_t res; +} __packed; + +struct itnl_exp_sb { + uint8_t reason; +#define TASK_F_W_OPEN_TO 0x03 +#define TASK_F_W_OPEN_REJECT 0x04 +#define TASK_F_W_PHY_DOWN 0x09 +#define TASK_F_W_BREAK_RCVD 0x0E + + union { + struct open_timeout_ssb open_timeout; + struct open_reject_ssb open_reject; + } stat_subblk; +}; + +#define ABANDON_OPEN_MASK 0x02 +#define RETRY_OPEN_MASK 0x01 + +/* Abandon Open Reject Reason field. */ +#define BAD_DESTINATION 0x00 +#define CONN_RATE_NOT_SUPPORTED 0x01 +#define PROTOCOL_NOT_SUPPORTED 0x02 +#define RSVD_ABANDON_0 0x03 +#define RSVD_ABANDON_1 0x04 +#define RSVD_ABANDON_2 0x05 +#define RSVD_ABANDON_3 0x06 +#define WRONG_DESTINATION 0x07 +#define STP_RESOURCE_BUSY 0x08 + +/* Retry Open Reject Reason field. */ +#define NO_DESTINATION 0x00 +#define PATHWAY_BLOCKED 0x10 +#define RSVD_CONTINUE_0 0x20 +#define RSVD_CONTINUE_1 0x30 +#define RSVD_INITIALIZE_0 0x40 +#define RSVD_INITIALIZE_1 0x50 +#define RSVD_STOP_0 0x60 +#define RSVD_STOP_1 0x70 +#define RETRY 0x80 + +/* Task Cleared format. */ +struct task_cleared_sb { + uint16_t tag_of_cleared_task; + uint16_t clr_nxs_ctx; +} __packed; + + +/* Empty Data Buffer Received format. */ +struct bytes_dmaed_subblk { + uint8_t protocol; /* + * MSB represent Initiator or + * Target. + */ +#define INIT_TGT_MASK 0x80 +#define PROTOCOL_MASK 0x70 + + uint16_t edb_len; /* + * The msb 5 bits are ignored. + */ +#define BYTES_DMAED_LEN_MASK 0x07FF +} __packed; + +struct primitive_rcvd_subblk { + uint8_t reg_addr; + uint8_t reg_content; + uint8_t res; +} __packed; + +struct phy_event_subblk { + uint8_t oob_status; + uint8_t oob_mode; + uint8_t oob_signals; +} __packed; + +struct link_reset_err_subblk { + uint8_t error; +#define RCVD_ID_TIMER_EXP 0x00 /* + * Timed out waiting for + * IDENTIFY Address frame + * from attached device. + */ +#define LOSS_OF_SIGNAL_ERR 0x01 /* + * Loss of signal detected + * following a completed PHY + * reset + */ +#define LOSS_OF_DWS_ERR 0x02 /* + * Loss of dword sync detected + * following a completed PHY + * reset. + */ +#define RCV_FIS_TIMER_EXP 0x03 /* + * Timed out waiting for initial + * Device-to-Host Register FIS + * from attached device. + */ + + /* Number of link reset retry attempts remaining */ + uint8_t cur_retry_cnt; + + int8_t res; +} __packed; + +struct timer_event_subblk { + uint8_t error; +#define DWS_RESET_TO_EXP 0x00 /* + * DWS reset timer timeout + * expired. + */ + uint16_t res; +} __packed; + +/* + * Common reasons shared by REQ TASK ABORT and REQ DEVICE RESET. + */ +#define TASK_UA_W_PHY_DOWN 0x0D + +struct req_task_abort_subblk { + uint16_t task_tc_to_abort; + uint8_t reason; +#define TASK_UA_W_BRK_RCVD 0x0E +#define TASK_UA_W_ACKNAK_TO 0x18 +} __packed; + +struct req_dev_reset_subblk { + uint16_t task_tc_to_abort; + uint8_t reason; +#define TASK_INT_W_SATA_TO 0x0F +#define TASK_UA_W_SATA_TO 0x19 +#define TASK_INT_W_SYNCS_RCVD 0x24 + +} __packed; + +struct edb_rcvd_sb { + uint8_t sb_opcode; + /* The opcode defintions below can be or'ed with Receiving Phy ID. */ +#define BYTES_DMAED 0x00 /* 00h - 07h */ +#define PRIMITIVE_RCVD 0x08 /* 08h - 0Fh */ +#define PHY_EVENT 0x10 /* 10h - 17h */ +#define LINK_RESET_ERR 0x18 /* 18h - 1Fh */ +#define TIMER_EVENT 0x20 /* 20h - 27h */ +#define ESTABLISH_CONN 0x28 /* 28h - 2Fh */ +#define REQ_TASK_ABORT 0xF0 +#define REQ_DEVICE_RESET 0xF1 +#define EDB_OPCODE_MASK 0x07 + + union { + struct bytes_dmaed_subblk bytes_dmaed; + struct primitive_rcvd_subblk prim_rcvd; + struct phy_event_subblk phy_event; + struct link_reset_err_subblk link_reset_err; + struct timer_event_subblk timer_event; + struct req_task_abort_subblk req_task_abort; + struct req_dev_reset_subblk req_dev_reset; + } edb_subblk; +} __packed; + +/* Done List format. */ +struct asd_done_list { + uint16_t index; + uint8_t opcode; + union { + struct generic_sb generic; + struct no_error_sb no_error; + struct data_underrun_sb data; + struct open_reject_sb open_reject; + struct response_sb response; + struct control_phy_sb control_phy; + struct itnl_exp_sb itnl_exp; + struct task_cleared_sb task_cleared; + struct task_cleared_sb resume_complete; + struct edb_rcvd_sb edb_rcvd; + } stat_blk; + uint8_t toggle; +#define ASD_DL_TOGGLE_MASK 0x1 +} __packed; + +struct asd_int_ddb { + uint8_t res1[10]; + uint16_t shared_mem_lock; + uint8_t res2[34]; + uint8_t conn_not_active; + uint8_t phy_is_up; + uint8_t port_map_by_ports[8]; + uint8_t port_map_by_links[8]; +} __packed; + +struct asd_ddb { + uint8_t addr_fr_port; +#define INITIATOR_PORT_MODE 0x80 +#define OPEN_ADDR_FRAME 0x01 + + uint8_t conn_rate; + uint16_t init_conn_tag; + uint8_t dest_sas_addr[8]; + uint16_t send_q_head; + uint8_t sqsuspended; + uint8_t ddb_type; +#define UNUSED_DDB 0xFF +#define TARGET_PORT_DDB 0xFE +#define INITIATOR_PORT_DDB 0xFD +#define PM_PORT_DDB 0xFC + + uint16_t res1; + uint16_t awt_default; + uint8_t comp_features; + uint8_t pathway_blk_cnt; + uint16_t arb_wait_time; + uint32_t more_comp_features; + uint8_t conn_mask; + uint8_t open_affl; +#define OPEN_AFFILIATION 0x01 +#define STP_AFFILIATION 0x20 +#define SUPPORTS_AFFILIATION 0x40 +#define SATA_MULTIPORT 0x80 + + uint8_t res2; + uint8_t stp_close; +#define CLOSE_STP_NO_TX 0x00 +#define CLOSE_STP_BTW_CMDS 0x01 +#define CLOSE_STP_NEVER 0x10 + + uint16_t exec_q_tail; + uint16_t send_q_tail; + uint16_t sister_ddb; + uint16_t ata_cmd_scb_ptr; + uint32_t sata_tag_mask; + uint16_t active_task_cnt; + uint16_t res3; + uint32_t sata_sactive; + uint8_t no_of_sata_tags; + uint8_t sata_stat; + uint8_t sata_ending_stat; + uint8_t itnl_reason; + uint16_t ncq_data_scb_ptr; + uint16_t itnl_const; +#define ITNL_TIMEOUT_CONST 0x7D0 /* 2 seconds */ + + uint32_t itnl_timestamp; +} __packed; + +struct asd_port_multi_ddb { + uint8_t res1[29]; + uint8_t multi_pm_port; +#define SATA_PORT_MULTI_DDB (1U << 1) +#define PM_PORT_SHIFT 4 +#define PM_PORT_MASK 0xF0 + + uint8_t res2; + uint8_t res3[5]; + uint16_t sister_ddb; + uint16_t ata_cmd_scb_ptr; + uint32_t sata_tag_alloc_mask; + uint16_t active_task_cnt; + uint16_t parent_ddb; + uint32_t sata_sactive_reg; + uint8_t sata_tags; + uint8_t sata_stat_reg; + uint8_t sata_end_stat_reg; + uint8_t res4[9]; +} __packed; + +struct asd_port_multi_table_ddb { + uint16_t ddb_ptr0; + uint16_t ddb_ptr1; + uint16_t ddb_ptr2; + uint16_t ddb_ptr3; + uint16_t ddb_ptr4; + uint16_t ddb_ptr5; + uint16_t ddb_ptr6; + uint16_t ddb_ptr7; + uint16_t ddb_ptr8; + uint16_t ddb_ptr9; + uint16_t ddb_ptr10; + uint16_t ddb_ptr11; + uint16_t ddb_ptr12; + uint16_t ddb_ptr13; + uint16_t ddb_ptr14; + uint16_t ddb_ptr15; + uint8_t res[32]; +} __packed; + +/* + * Transport specific (SAS and SATA) data structures. + */ +struct sas_id_addr { + uint8_t addr_frame_type; /* + * Bits 0-3: Address Frame Type + * 4-6: Device Type + * 7: Restricted + */ +#define SAS_END_DEVICE (1U << 4) +#define SAS_EDGE_EXP_DEVICE (1U << 5) +#define SAS_FANOUT_EXP_DEVICE (1U << 6) +#define SAS_DEVICE_MASK 0x70 + + uint8_t restricted1; + uint8_t init_port_type; +#define SMP_INIT_PORT (1U << 1) +#define STP_INIT_PORT (1U << 2) +#define SSP_INIT_PORT (1U << 3) +#define INIT_PORT_MASK 0x0E + + uint8_t tgt_port_type; +#define SATA_TGT_PORT (1U << 0) +#define SMP_TGT_PORT (1U << 1) +#define STP_TGT_PORT (1U << 2) +#define SSP_TGT_PORT (1U << 3) +#define TGT_PORT_MASK 0x0E + + uint8_t restricted2[8]; + uint8_t sas_addr[8]; + uint8_t phy_id; + uint8_t res[7]; + uint8_t crc[4]; +} __packed; + +struct sas_initial_fis { + uint8_t fis[20]; +}; + +union sas_bytes_dmaed { + struct sas_id_addr id_addr_rcvd; + struct sas_initial_fis initial_fis_rcvd; +}; + +void asd_hwi_hash(uint8_t *sas_addr, uint8_t *hashed_addr); + +#define ASD_MAX_DATA_PAT_GEN_SIZE_TX 1024 +#define ASD_MAX_DATA_PAT_GEN_SIZE_RX 2176 + +#endif /* ADP94XX_SAS_H */