// SPDX-License-Identifier: MPL-2.0
//
// Do NOT modify or remove this copyright and license
//
// Copyright (c) 2012-2026 Seagate Technology LLC and/or its Affiliates, All Rights Reserved
//
// This software is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// ******************************************************************************************
//
// \file sas_phy.h
// \brief This file holds options to do things on a SAS phy.

#pragma once

#if defined(__cplusplus)
extern "C"
{
#endif

#include "precision_timer.h"

#include "operations_Common.h"
#include "scsi_helper.h"
#include "scsi_helper_func.h"

// checks if it is SAS protocol and Diagnostic page 3F is supported
//! \def SAS_SUPPORTED_DIAGNOSTIC_PAGES_PROBE_LENGTH
//! \brief Allocation length for the RECEIVE DIAGNOSTIC RESULTS probe used to check
//!        which SAS diagnostic pages are supported (SEND/RECEIVE DIAGNOSTIC page 0x00).
//!        The theoretical maximum is SCSI_DIAG_PAGE_HEADER_LENGTH (4) + 256 page codes = 260 bytes.
//!        50 bytes is a pragmatic probe size sufficient to detect all pages used by these tools.
#define SAS_SUPPORTED_DIAGNOSTIC_PAGES_PROBE_LENGTH UINT16_C(50)

    M_PARAM_RO(1) OPENSEA_OPERATIONS_API bool is_SAS_Phy_Diagnostic_Page_Supported(const tDevice* M_NONNULL device);

    typedef enum eSASPhyTestPatternEnum
    {
        SAS_PHY_PATTERN_RESERVED = 0x00,
        SAS_PHY_PATTERN_JTPAT    = 0x01,
        SAS_PHY_PATTERN_CJTPAT   = 0x02,
        SAS_PHY_PATTERN_PRBS9    = 0x03,
        SAS_PHY_PATTERN_PRRBS15  = 0x04,
        // 05 - 0F are reserved
        SAS_PHY_PATTERN_TRAIN       = 0x10,
        SAS_PHY_PATTERN_TRAIN_DONE  = 0x11,
        SAS_PHY_PATTERN_IDLE        = 0x12,
        SAS_PHY_PATTERN_SCRAMBLED_0 = 0x13,
        // 14 - 3F are reserved
        SAS_PHY_PATTERN_TWO_DWORDS = 0x40,
        // 41 - EF are reserved
        // F0 - FF : Vendor Specific
        SAS_PHY_PATTERN_BEGIN_VENDOR_UNIQUE = 0xF0,
    } eSASPhyTestPattern;

    typedef enum eSASPhyTestFunctionEnum
    {
        SAS_PHY_FUNC_STOP             = 0x00,
        SAS_PHY_FUNC_TRANSMIT_PATTERN = 0x01,
        // 02 - EF are reserved
        // D0 - FF are vendor specific
    } eSASPhyTestFunction;

    typedef enum eSASPhyTestFunctionSSCEnum
    {
        SAS_PHY_SSC_NO_SPREADING     = 0x00,
        SAS_PHY_SSC_CENTER_SPREADING = 0x01,
        SAS_PHY_SSC_DOWN_SPREADING   = 0x02,
        SAS_PHY_SSC_RESERVED         = 0x03
    } eSASPhyTestFunctionSSC;

    typedef enum eSASPhyPhysicalLinkRateEnum
    {
        SAS_PHY_LINK_RATE_1_5G  = 0x08,
        SAS_PHY_LINK_RATE_3G    = 0x09,
        SAS_PHY_LINK_RATE_6G    = 0x0A,
        SAS_PHY_LINK_RATE_12G   = 0x0B,
        SAS_PHY_LINK_RATE_22_5G = 0x0C
    } eSASPhyPhysicalLinkRate;

    typedef enum eSASPhyDwordControlEnum
    {
        SAS_PHY_DWORD_CONTROL_DATA_CHARACTER_NO_SCRAMBLING                     = 0x00,
        SAS_PHY_DWORD_CONTROL_5TH_BYTE_CONTROL_CHARACTER_NO_SCRAMBLING         = 0x08,
        SAS_PHY_DWORD_CONTROL_1ST_BYTE_CONTROL_CHARACTER_NO_SCRAMBLING         = 0x80,
        SAS_PHY_DWORD_CONTROL_1ST_AND_5TH_BYTE_CONTROL_CHARACTER_NO_SCRAMBLING = 0x88,
        // all others are reserved
    } eSASPhyDwordControl;

#define PHY_TEST_PATTERN_DWORD_D10_2          UINT64_C(0x4A4A4A4A4A4A4A4A)
#define PHY_TEST_PATTERN_DWORD_D21_5          UINT64_C(0xB5B5B5B5B5B5B5B5)
#define PHY_TEST_PATTERN_DWORD_D24_3          UINT64_C(0x7878787878787878)
#define PHY_TEST_PATTERN_DWORD_D25_6_AND_D6_1 UINT64_C(0xD926D926D926D926)
#define PHY_TEST_PATTERN_DWORD_D30_3          UINT64_C(0x7E7E7E7E7E7E7E7E)
#define PHY_TEST_PATTERN_DWORD_ALIGN_0        UINT64_C(0xBC4A4A7BBC4A4A7B)
#define PHY_TEST_PATTERN_DWORD_ALIGN_1        UINT64_C(0xBC070707BC070707)
#define PHY_TEST_PATTERN_DWORD_PAIR_ALIGN_0   UINT64_C(0xBC4A4A7B4A787E7E)

    // Takes all the inputs to start a test pattern
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues start_SAS_Test_Pattern(const tDevice* M_NONNULL device,
                                                                uint8_t                  phyIdentifier,
                                                                eSASPhyTestPattern       pattern,
                                                                bool                     sataTestFunction,
                                                                eSASPhyTestFunctionSSC   testFunctionSSC,
                                                                eSASPhyPhysicalLinkRate  linkRate,
                                                                eSASPhyDwordControl      dwordControl,
                                                                uint64_t                 phyTestPatternDwords);

    // will stop a test pattern on a specified phy
    M_PARAM_RO(1)
    OPENSEA_OPERATIONS_API eReturnValues stop_SAS_Test_Pattern(const tDevice* M_NONNULL device,
                                                               uint8_t                  phyIdentifier,
                                                               eSASPhyPhysicalLinkRate  linkRate);

#if defined(__cplusplus)
}
#endif
