diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/data/hdcp1x.mdd b/XilinxProcessorIPLib/drivers/hdcp1x/data/hdcp1x.mdd new file mode 100644 index 00000000..374e89a3 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/data/hdcp1x.mdd @@ -0,0 +1,41 @@ +################################################################################ + # + # Copyright (C) 2015 Xilinx, Inc. All rights reserved. + # + # Permission is hereby granted, free of charge, to any person obtaining a copy + # of this software and associated documentation files (the "Software"), to deal + # in the Software without restriction, including without limitation the rights + # to use, copy, modify, merge, publish, distribute, sublicense, and#or sell + # copies of the Software, and to permit persons to whom the Software is + # furnished to do so, subject to the following conditions: + # + # The above copyright notice and this permission notice shall be included in + # all copies or substantial portions of the Software. + # + # Use of the Software is limited solely to applications: + # (a) running on a Xilinx device, or + # (b) that interact with a Xilinx device through a bus or interconnect. + # + # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + # XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + # SOFTWARE. + # + # Except as contained in this notice, the name of the Xilinx shall not be used + # in advertising or otherwise to promote the sale, use or other dealings in + # this Software without prior written authorization from Xilinx. + # +################################################################################ + +OPTION psf_version = 2.1; + +BEGIN driver hdcp1x + OPTION supported_peripherals = (hdmi_tx_hdcp_cipher_4b hdmi_rx_hdcp_cipher_4b hdcp); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 1.0; + OPTION NAME = hdcp1x; +END driver diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/data/hdcp1x.tcl b/XilinxProcessorIPLib/drivers/hdcp1x/data/hdcp1x.tcl new file mode 100644 index 00000000..d6f4b0ec --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/data/hdcp1x.tcl @@ -0,0 +1,37 @@ +################################################################################ + # + # Copyright (C) 2015 Xilinx, Inc. All rights reserved. + # + # Permission is hereby granted, free of charge, to any person obtaining a copy + # of this software and associated documentation files (the "Software"), to deal + # in the Software without restriction, including without limitation the rights + # to use, copy, modify, merge, publish, distribute, sublicense, and#or sell + # copies of the Software, and to permit persons to whom the Software is + # furnished to do so, subject to the following conditions: + # + # The above copyright notice and this permission notice shall be included in + # all copies or substantial portions of the Software. + # + # Use of the Software is limited solely to applications: + # (a) running on a Xilinx device, or + # (b) that interact with a Xilinx device through a bus or interconnect. + # + # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + # XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + # SOFTWARE. + # + # Except as contained in this notice, the name of the Xilinx shall not be used + # in advertising or otherwise to promote the sale, use or other dealings in + # this Software without prior written authorization from Xilinx. + # +################################################################################ + +proc generate {drv_handle} { + ::hsi::utils::define_include_file $drv_handle "xparameters.h" "XHDCP" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_S_AXI_FREQUENCY" "C_IS_RX" "C_IS_HDMI" + ::hsi::utils::define_config_file $drv_handle "xhdcp1x_g.c" "XHdcp1x" "DEVICE_ID" "C_BASEADDR" "C_S_AXI_FREQUENCY" "C_IS_RX" "C_IS_HDMI" + ::hsi::utils::define_canonical_xpars $drv_handle "xparameters.h" "XHDCP" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_S_AXI_FREQUENCY" "C_IS_RX" "C_IS_HDMI" +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/Makefile b/XilinxProcessorIPLib/drivers/hdcp1x/src/Makefile new file mode 100644 index 00000000..cd17ff37 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/Makefile @@ -0,0 +1,28 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +INCLUDEFILES=xhdcp1x.h xhdcp1x_port.h + +LIBSOURCES=*.c +OUTS = *.o + + +libs: + echo "Compiling hdcp1x" + $(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES) + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} $(OUTS) + make clean + +include: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OUTS} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/sha1.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/sha1.c new file mode 100644 index 00000000..f0c95dcb --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/sha1.c @@ -0,0 +1,389 @@ +/* + * sha1.c + * + * Description: + * This file implements the Secure Hashing Algorithm 1 as + * defined in FIPS PUB 180-1 published April 17, 1995. + * + * The SHA-1, produces a 160-bit message digest for a given + * data stream. It should take about 2**n steps to find a + * message with the same digest as a given message and + * 2**(n/2) to find any two messages with the same digest, + * when n is the digest size in bits. Therefore, this + * algorithm can serve as a means of providing a + * "fingerprint" for a message. + * + * Portability Issues: + * SHA-1 is defined in terms of 32-bit "words". This code + * uses (included via "sha1.h" to define 32 and 8 + * bit unsigned integer types. If your C compiler does not + * support 32 bit unsigned integers, this code is not + * appropriate. + * + * Caveats: + * SHA-1 is designed to work with messages less than 2^64 bits + * long. Although SHA-1 allows a message digest to be generated + * for messages of any number of bits less than 2^64, this + * implementation only works with messages with a length that is + * a multiple of the size of an 8-bit character. + * + */ + +#include "sha1.h" + +/* + * Define the SHA1 circular left shift macro + */ +#define SHA1CircularShift(bits,word) \ + (((word) << (bits)) | ((word) >> (32-(bits)))) + +/* Local Function Prototyptes */ +void SHA1PadMessage(SHA1Context *); +void SHA1ProcessMessageBlock(SHA1Context *); + +/* + * SHA1Reset + * + * Description: + * This function will initialize the SHA1Context in preparation + * for computing a new SHA1 message digest. + * + * Parameters: + * context: [in/out] + * The context to reset. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Reset(SHA1Context *context) +{ + if (!context) + { + return shaNull; + } + + context->Length_Low = 0; + context->Length_High = 0; + context->Message_Block_Index = 0; + + context->Intermediate_Hash[0] = 0x67452301; + context->Intermediate_Hash[1] = 0xEFCDAB89; + context->Intermediate_Hash[2] = 0x98BADCFE; + context->Intermediate_Hash[3] = 0x10325476; + context->Intermediate_Hash[4] = 0xC3D2E1F0; + + context->Computed = 0; + context->Corrupted = 0; + + return shaSuccess; +} + +/* + * SHA1Result + * + * Description: + * This function will return the 160-bit message digest into the + * Message_Digest array provided by the caller. + * NOTE: The first octet of hash is stored in the 0th element, + * the last octet of hash in the 19th element. + * + * Parameters: + * context: [in/out] + * The context to use to calculate the SHA-1 hash. + * Message_Digest: [out] + * Where the digest is returned. + * + * Returns: + * sha Error Code. + * + */ +int SHA1Result( SHA1Context *context, + uint8_t Message_Digest[SHA1HashSize]) +{ + int i; + + if (!context || !Message_Digest) + { + return shaNull; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + + if (!context->Computed) + { + SHA1PadMessage(context); + for(i=0; i<64; ++i) + { + /* message may be sensitive, clear it out */ + context->Message_Block[i] = 0; + } + context->Length_Low = 0; /* and clear length */ + context->Length_High = 0; + context->Computed = 1; + + } + + for(i = 0; i < SHA1HashSize; ++i) + { + Message_Digest[i] = context->Intermediate_Hash[i>>2] + >> 8 * ( 3 - ( i & 0x03 ) ); + } + + return shaSuccess; +} + +/* + * SHA1Input + * + * Description: + * This function accepts an array of octets as the next portion + * of the message. + * + * Parameters: + * context: [in/out] + * The SHA context to update + * message_array: [in] + * An array of characters representing the next portion of + * the message. + * length: [in] + * The length of the message in message_array + * + * Returns: + * sha Error Code. + * + */ +int SHA1Input( SHA1Context *context, + const uint8_t *message_array, + unsigned length) +{ + if (!length) + { + return shaSuccess; + } + + if (!context || !message_array) + { + return shaNull; + } + + if (context->Computed) + { + context->Corrupted = shaStateError; + + return shaStateError; + } + + if (context->Corrupted) + { + return context->Corrupted; + } + while(length-- && !context->Corrupted) + { + context->Message_Block[context->Message_Block_Index++] = + (*message_array & 0xFF); + + context->Length_Low += 8; + if (context->Length_Low == 0) + { + context->Length_High++; + if (context->Length_High == 0) + { + /* Message is too long */ + context->Corrupted = 1; + } + } + + if (context->Message_Block_Index == 64) + { + SHA1ProcessMessageBlock(context); + } + + message_array++; + } + + return shaSuccess; +} + +/* + * SHA1ProcessMessageBlock + * + * Description: + * This function will process the next 512 bits of the message + * stored in the Message_Block array. + * + * Parameters: + * None. + * + * Returns: + * Nothing. + * + * Comments: + + * Many of the variable names in this code, especially the + * single character names, were used because those were the + * names used in the publication. + * + * + */ +void SHA1ProcessMessageBlock(SHA1Context *context) +{ + const uint32_t K[] = { /* Constants defined in SHA-1 */ + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + int t; /* Loop counter */ + uint32_t temp; /* Temporary word value */ + uint32_t W[80]; /* Word sequence */ + uint32_t A, B, C, D, E; /* Word buffers */ + + /* + * Initialize the first 16 words in the array W + */ + for(t = 0; t < 16; t++) + { + W[t] = context->Message_Block[t * 4] << 24; + W[t] |= context->Message_Block[t * 4 + 1] << 16; + W[t] |= context->Message_Block[t * 4 + 2] << 8; + W[t] |= context->Message_Block[t * 4 + 3]; + } + + for(t = 16; t < 80; t++) + { + W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); + } + + A = context->Intermediate_Hash[0]; + B = context->Intermediate_Hash[1]; + C = context->Intermediate_Hash[2]; + D = context->Intermediate_Hash[3]; + E = context->Intermediate_Hash[4]; + + for(t = 0; t < 20; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + + B = A; + A = temp; + } + + for(t = 20; t < 40; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 40; t < 60; t++) + { + temp = SHA1CircularShift(5,A) + + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + for(t = 60; t < 80; t++) + { + temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; + E = D; + D = C; + C = SHA1CircularShift(30,B); + B = A; + A = temp; + } + + context->Intermediate_Hash[0] += A; + context->Intermediate_Hash[1] += B; + context->Intermediate_Hash[2] += C; + context->Intermediate_Hash[3] += D; + context->Intermediate_Hash[4] += E; + + context->Message_Block_Index = 0; +} + +/* + * SHA1PadMessage + * + + * Description: + * According to the standard, the message must be padded to an even + * 512 bits. The first padding bit must be a '1'. The last 64 + * bits represent the length of the original message. All bits in + * between should be 0. This function will pad the message + * according to those rules by filling the Message_Block array + * accordingly. It will also call the ProcessMessageBlock function + * provided appropriately. When it returns, it can be assumed that + * the message digest has been computed. + * + * Parameters: + * context: [in/out] + * The context to pad + * ProcessMessageBlock: [in] + * The appropriate SHA*ProcessMessageBlock function + * Returns: + * Nothing. + * + */ + +void SHA1PadMessage(SHA1Context *context) +{ + /* + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second + * block. + */ + if (context->Message_Block_Index > 55) + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 64) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + + SHA1ProcessMessageBlock(context); + + while(context->Message_Block_Index < 56) + { + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + else + { + context->Message_Block[context->Message_Block_Index++] = 0x80; + while(context->Message_Block_Index < 56) + { + + context->Message_Block[context->Message_Block_Index++] = 0; + } + } + + /* + * Store the message length as the last 8 octets + */ + context->Message_Block[56] = context->Length_High >> 24; + context->Message_Block[57] = context->Length_High >> 16; + context->Message_Block[58] = context->Length_High >> 8; + context->Message_Block[59] = context->Length_High; + context->Message_Block[60] = context->Length_Low >> 24; + context->Message_Block[61] = context->Length_Low >> 16; + context->Message_Block[62] = context->Length_Low >> 8; + context->Message_Block[63] = context->Length_Low; + + SHA1ProcessMessageBlock(context); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/sha1.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/sha1.h new file mode 100644 index 00000000..eb51ed56 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/sha1.h @@ -0,0 +1,73 @@ +/* + * sha1.h + * + * Description: + * This is the header file for code which implements the Secure + * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published + * April 17, 1995. + * + * Many of the variable names in this code, especially the + * single character names, were used because those were the names + * used in the publication. + * + * Please read the file sha1.c for more information. + * + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#include +/* + * If you do not have the ISO standard stdint.h header file, then you + * must typdef the following: + * name meaning + * uint32_t unsigned 32 bit integer + * uint8_t unsigned 8 bit integer (i.e., unsigned char) + * int_least16_t integer of >= 16 bits + * + */ + +#ifndef _SHA_enum_ +#define _SHA_enum_ +enum +{ + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError /* called Input after Result */ +}; +#endif +#define SHA1HashSize 20 + +/* + * This structure will hold context information for the SHA-1 + * hashing operation + */ +typedef struct SHA1Context +{ + uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ + + uint32_t Length_Low; /* Message length in bits */ + uint32_t Length_High; /* Message length in bits */ + + /* Index into message block array */ + int_least16_t Message_Block_Index; + uint8_t Message_Block[64]; /* 512-bit message blocks */ + + int Computed; /* Is the digest computed? */ + int Corrupted; /* Is the message digest corrupted? */ +} SHA1Context; + +/* + * Function Prototypes + */ + +int SHA1Reset( SHA1Context *); +int SHA1Input( SHA1Context *, + const uint8_t *, + unsigned int); +int SHA1Result( SHA1Context *, + uint8_t Message_Digest[SHA1HashSize]); + +#endif diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x.c new file mode 100644 index 00000000..4eeccfe4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x.c @@ -0,0 +1,1005 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xhdcp1x.c +* +* This contains the implementation of the HDCP state machine module +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "xhdcp1x.h" +#include "xhdcp1x_cipher.h" +#include "xhdcp1x_debug.h" +#include "xhdcp1x_port.h" +#include "xhdcp1x_rx.h" +#include "xhdcp1x_tx.h" +#include "xil_types.h" +#include "xparameters.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ +#if defined(XPAR_XHDMI_TX_NUM_INSTANCES) && (XPAR_XHDMI_TX_NUM_INSTANCES > 0) + #define INCLUDE_TX +#endif +#if defined(XPAR_XHDMI_RX_NUM_INSTANCES) && (XPAR_XHDMI_RX_NUM_INSTANCES > 0) + #define INCLUDE_RX +#endif +#if defined(XPAR_XDP_NUM_INSTANCES) && (XPAR_XDP_NUM_INSTANCES > 0) + #define INCLUDE_RX + #define INCLUDE_TX +#endif + +/** + * This defines the version of the software driver + */ +#define DRIVER_VERSION (0x00010023ul) + +/**************************** Type Definitions *******************************/ + +/************************** Extern Declarations ******************************/ + +/************************** Global Declarations ******************************/ +XHdcp1x_Printf XHdcp1xDebugPrintf = NULL; +XHdcp1x_LogMsg XHdcp1xDebugLogMsg = NULL; +XHdcp1x_KsvRevokeCheck XHdcp1xKsvRevokeCheck = NULL; +XHdcp1x_TimerStart XHdcp1xTimerStart = NULL; +XHdcp1x_TimerStop XHdcp1xTimerStop = NULL; +XHdcp1x_TimerDelay XHdcp1xTimerDelay = NULL; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is a receiver +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating receiver (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsRX(InstancePtr) (InstancePtr->Common.CfgPtr->IsRx) + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is a transmitter +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating transmitter (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsTX(InstancePtr) (!InstancePtr->Common.CfgPtr->IsRx) + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is Display Port (DP) +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating DP (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsDP(InstancePtr) (!InstancePtr->Common.CfgPtr->IsHDMI) + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is HDMI +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating HDMI (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsHDMI(InstancePtr) (InstancePtr->Common.CfgPtr->IsHDMI) + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function determines the adaptor for a specified port device +* +* @param InstancePtr the device whose adaptor is to be determined +* @param CfgPtr the configuration of the instance +* @param PhyIfPtr pointer to the underlying physical interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CfgInitialize(XHdcp1x *InstancePtr, const XHdcp1x_Config *CfgPtr, + void* PhyIfPtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + Xil_AssertNonvoid(InstancePtr->Common.IsReady != + XIL_COMPONENT_IS_READY); + + /* Initialize InstancePtr */ + memset(InstancePtr, 0, sizeof(XHdcp1x)); + InstancePtr->Common.CfgPtr = CfgPtr; + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxCfgInitialize(&(InstancePtr->Tx), + CfgPtr, PhyIfPtr); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + Status = XHdcp1x_RxCfgInitialize(&(InstancePtr->Rx), + CfgPtr, PhyIfPtr); + } + else +#endif + { + Status = XST_FAILURE; + } + + /* Update IsReady */ + if (Status == XST_SUCCESS) { + InstancePtr->Common.IsReady = XIL_COMPONENT_IS_READY; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function polls an hdcp interface +* +* @param InstancePtr the interface to poll +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_Poll(XHdcp1x *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxPoll(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + Status = XHdcp1x_RxPoll(&(InstancePtr->Rx)); + } + else +#endif + { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function resets an hdcp interface +* +* @param InstancePtr the interface to reset +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_Reset(XHdcp1x *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxReset(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + Status = XHdcp1x_RxReset(&(InstancePtr->Rx)); + } + else +#endif + { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function enables an hdcp interface +* +* @param InstancePtr the interface to enable +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_Enable(XHdcp1x *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxEnable(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + Status = XHdcp1x_RxEnable(&(InstancePtr->Rx)); + } + else +#endif + { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables an hdcp interface +* +* @param InstancePtr the interface to disable +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_Disable(XHdcp1x *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxDisable(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + Status = XHdcp1x_RxDisable(&(InstancePtr->Rx)); + } + else +#endif + { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function updates the state of the underlying physical interface +* +* @param InstancePtr the interface to update +* @param IsUp truth value indicating the underlying physical interface state +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_SetPhysicalState(XHdcp1x *InstancePtr, int IsUp) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxSetPhysicalState(&(InstancePtr->Tx), IsUp); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + Status = XHdcp1x_RxSetPhysicalState(&(InstancePtr->Rx), IsUp); + } + else +#endif + { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function sets the lane count of a hdcp interface +* +* @param InstancePtr the interface to update +* @param LaneCount the lane count +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_SetLaneCount(XHdcp1x *InstancePtr, int LaneCount) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if ((IsTX(InstancePtr)) && (IsDP(InstancePtr))) { + Status = XHdcp1x_TxSetLaneCount(&(InstancePtr->Tx), LaneCount); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if ((IsRX(InstancePtr)) && (IsDP(InstancePtr))) { + Status = XHdcp1x_RxSetLaneCount(&(InstancePtr->Rx), LaneCount); + } + else +#endif + { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function initiates authentication of an hdcp interface +* +* @param InstancePtr the interface to initiate authentication on +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_Authenticate(XHdcp1x *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxAuthenticate(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + Status = XHdcp1x_RxAuthenticate(&(InstancePtr->Rx)); + } + else +#endif + { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function queries an interface to determine if authentication is in +* progress +* +* @param InstancePtr the interface to query +* +* @return +* Truth value indicating authentication in progress (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_IsInProgress(const XHdcp1x *InstancePtr) +{ + int IsInProgress = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + IsInProgress = XHdcp1x_TxIsInProgress(&(InstancePtr->Tx)); + } +#endif + + return (IsInProgress); +} + +/*****************************************************************************/ +/** +* +* This function queries an interface to determine if it has successfully +* completed authentication +* +* @param InstancePtr the interface to query +* +* @return +* Truth value indicating authenticated (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_IsAuthenticated(const XHdcp1x *InstancePtr) +{ + int IsAuth = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + IsAuth = XHdcp1x_TxIsAuthenticated(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + IsAuth = XHdcp1x_RxIsAuthenticated(&(InstancePtr->Rx)); + } + else +#endif + { + IsAuth = FALSE; + } + + return (IsAuth); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the current encryption map of the video streams +* traversing an hdcp interface +* +* @param InstancePtr the interface to query +* +* @return +* The current encryption map +* +* @note +* None. +* +******************************************************************************/ +u64 XHdcp1x_GetEncryption(const XHdcp1x *InstancePtr) +{ + u64 StreamMap = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + StreamMap = XHdcp1x_TxGetEncryption(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + StreamMap = XHdcp1x_RxGetEncryption(&(InstancePtr->Rx)); + } + else +#endif + { + StreamMap = 0; + } + + return (StreamMap); +} + +/*****************************************************************************/ +/** +* +* This function enables encryption on a series of streams within an hdcp +* interface +* +* @param InstancePtr the interface to configure +* @param Map the stream map to enable encryption on +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_EnableEncryption(XHdcp1x *InstancePtr, u64 Map) +{ + int Status = XST_FAILURE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxEnableEncryption(&(InstancePtr->Tx), Map); + } +#endif + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables encryption on a series of streams within an hdcp +* interface +* +* @param InstancePtr the interface to configure +* @param Map the stream map to disable encryption on +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_DisableEncryption(XHdcp1x *InstancePtr, u64 Map) +{ + int Status = XST_FAILURE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + Status = XHdcp1x_TxDisableEncryption(&(InstancePtr->Tx), Map); + } +#endif + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function sets the key selection vector that is to be used by the hdcp +* cipher +* +* @param InstancePtr the interface to configure +* @param KeySelect the key selection vector +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_SetKeySelect(XHdcp1x *InstancePtr, u8 KeySelect) +{ + XHdcp1x_Cipher *CipherPtr = NULL; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + CipherPtr = &(InstancePtr->Tx.Cipher); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + CipherPtr = &(InstancePtr->Rx.Cipher); + } + else +#endif + { + CipherPtr = NULL; + } + + /* Set it */ + if (CipherPtr != NULL) { + Status = XHdcp1x_CipherSetKeySelect(CipherPtr, KeySelect); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function handles a timeout on an hdcp interface +* +* @param InstancePtr the interface +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_HandleTimeout(void *InstancePtr) +{ + XHdcp1x *HdcpPtr = InstancePtr; + + /* Verify arguments. */ + Xil_AssertVoid(HdcpPtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(HdcpPtr)) { + XHdcp1x_TxHandleTimeout(&(HdcpPtr->Tx)); + } +#endif + + return; +} + + +/*****************************************************************************/ +/** +* +* This function sets the debug printf function for the module +* +* @param PrintfFunc the printf function +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_SetDebugPrintf(XHdcp1x_Printf PrintfFunc) +{ + XHdcp1xDebugPrintf = PrintfFunc; + return; +} + +/*****************************************************************************/ +/** +* +* This function sets the debug log message function for the module +* +* @param LogFunc the debug logging function +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_SetDebugLogMsg(XHdcp1x_LogMsg LogFunc) +{ + XHdcp1xDebugLogMsg = LogFunc; + return; +} + +/*****************************************************************************/ +/** +* +* This function sets the KSV revocation list check function for the module +* +* @param RevokeCheckFunc the KSV revocation list check function +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_SetKsvRevokeCheck(XHdcp1x_KsvRevokeCheck RevokeCheckFunc) +{ + XHdcp1xKsvRevokeCheck = RevokeCheckFunc; + return; +} + +/*****************************************************************************/ +/** +* +* This function sets timer start function for the module +* +* @param TimerStartFunc the timer start function +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_SetTimerStart(XHdcp1x_TimerStart TimerStartFunc) +{ + XHdcp1xTimerStart = TimerStartFunc; + return; +} + +/*****************************************************************************/ +/** +* +* This function sets timer stop function for the module +* +* @param TimerStopFunc the timer stop function +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_SetTimerStop(XHdcp1x_TimerStop TimerStopFunc) +{ + XHdcp1xTimerStop = TimerStopFunc; + return; +} + +/*****************************************************************************/ +/** +* +* This function sets timer busy delay function for the module +* +* @param TimerDelayFunc the timer busy delay function +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_SetTimerDelay(XHdcp1x_TimerDelay TimerDelayFunc) +{ + XHdcp1xTimerDelay = TimerDelayFunc; + return; +} + +/*****************************************************************************/ +/** +* +* This function retrieves the version of the hdcp driver software +* +* @return +* The software driver version +* +* @note +* None. +* +******************************************************************************/ +u32 XHdcp1x_GetDriverVersion(void) +{ + return (DRIVER_VERSION); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the cipher version of an hdcp interface +* +* @param InstancePtr the interface to query +* +* @return +* The cipher version used by the interface +* +* @note +* None. +* +******************************************************************************/ +u32 XHdcp1x_GetVersion(const XHdcp1x *InstancePtr) +{ + const XHdcp1x_Cipher *CipherPtr = NULL; + u32 Version = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + CipherPtr = &(InstancePtr->Tx.Cipher); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + CipherPtr = &(InstancePtr->Rx.Cipher); + } + else +#endif + { + CipherPtr = NULL; + } + + /* Set it */ + if (CipherPtr != NULL) { + Version = XHdcp1x_CipherGetVersion(CipherPtr); + } + + return (Version); +} + +/*****************************************************************************/ +/** +* +* This function performs a debug display of an hdcp instance +* +* @param InstancePtr the interface to display +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_Info(const XHdcp1x *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + +#if defined(INCLUDE_TX) + /* Check for TX */ + if (IsTX(InstancePtr)) { + XHdcp1x_TxInfo(&(InstancePtr->Tx)); + } + else +#endif +#if defined(INCLUDE_RX) + /* Check for RX */ + if (IsRX(InstancePtr)) { + XHdcp1x_RxInfo(&(InstancePtr->Rx)); + } + else +#endif + { + XHDCP_DEBUG_PRINTF("unknown interface type\r\n"); + } + + return; +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x.h new file mode 100644 index 00000000..09741548 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x.h @@ -0,0 +1,293 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x.h +* +* This header file contains the external declarations associated with the +* HDCP interface driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ +#ifndef XHDCP1X_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_types.h" +#include "xstatus.h" +#include "xtmrctr.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef defines the callback interface that is to be used for + * interrupts within this driver + */ +typedef void (*XHdcp1x_Callback)(void *CallbackRef); + +/** + * This typedef defines the function interface that is to be used for debug + * print statements within this driver + */ +typedef void (*XHdcp1x_Printf)(const char* fmt, ...); + +/** + * This typedef defines the function interface that is to be used for debug + * log message statements within this driver + */ +typedef void (*XHdcp1x_LogMsg)(const char* fmt, ...); + +/** +* This typedef contains configuration information for the HDCP core. +*/ +typedef struct { + u16 DeviceId; /**< Device instance ID. */ + u32 BaseAddress; /**< The base address of the core */ + u32 SysFrequency; /**< The main clock frequency of the core */ + u16 IsRx; /**< Flag indicating the core direction */ + u16 IsHDMI; /**< Flag indicating the core type */ +} XHdcp1x_Config; + +/** +* This typedef defines the statistics collected by a cipher instance +*/ +typedef struct { + u32 IntCount; /**< The number of interrupts detected */ +} XHdcp1x_CipherStats; + +/** +* This typedef contains an instance of the HDCP cipher core +*/ +typedef struct { + const XHdcp1x_Config *CfgPtr; /**< The cipher core config */ + u32 IsReady; /**< The ready flag */ + XHdcp1x_Callback LinkFailCallback; /**< Link fail callback */ + void *LinkFailRef; /**< Link fail reference */ + u32 IsLinkFailCallbackSet; /**< Link fail config flag */ + XHdcp1x_Callback RiUpdateCallback; /**< Ri update callback */ + void *RiUpdateRef; /**< Ri update reference */ + u32 IsRiUpdateCallbackSet; /**< Ri update config flag */ + XHdcp1x_CipherStats Stats; /**< Cipher statistics */ +} XHdcp1x_Cipher; + +/** +* This typedef defines the statistics collected by a port instance +*/ +typedef struct { + u32 IntCount; /**< The number of interrupts detected */ +} XHdcp1x_PortStats; + +/** + * Forward declaration of a structure defined within xhdcxp1x_port.h + */ +struct XHdcp1x_PortPhyIfAdaptorS; + +/** + * This typedef contains an instance of the HDCP port + */ +typedef struct XHdcp1x_PortStruct { + const XHdcp1x_Config *CfgPtr; /**< The cipher core config */ + const struct XHdcp1x_PortPhyIfAdaptorS *Adaptor; /**< Port adaptor */ + void *PhyIfPtr; /**< The port's physical interface */ + u32 IsReady; /**< The ready flag */ + XHdcp1x_Callback AuthCallback; /**< (Re)Authentication callback */ + void *AuthRef; /**< (Re)Authentication reference */ + u32 IsAuthCallbackSet; /**< (Re)Authentication config flag */ + XHdcp1x_PortStats Stats; /**< Port statistics */ +} XHdcp1x_Port; + +/** +* This typedef defines the statistics collected transmit port instance +*/ +typedef struct { + u32 AuthFailed; /**< Num of failed authentication attempts */ + u32 AuthPassed; /**< Num of passed authentication attempts */ + u32 ReauthRequested; /**< Num of rxd re-authentication requests */ + u32 ReadFailures; /**< Num of remote read failures */ + u32 LinkCheckPassed; /**< Num of link verifications that passed */ + u32 LinkCheckFailed; /**< Num of link verifications that failed */ +} XHdcp1x_TxStats; + +/** +* This typedef defines the statistics collected receive port instance +*/ +typedef struct { + u32 AuthAttempts; /**< Num of rxd authentication requests */ + u32 LinkFailures; /**< Num of link verifications that failed */ + u32 RiUpdates; /**< Num of Ri updates performed */ +} XHdcp1x_RxStats; + +/** +* This typedef defines the elements that are common to both RX and TX HDCP +* interfaces. The fields within this typedef must align with both the RX +* and TX definitions +*/ +typedef struct { + const XHdcp1x_Config *CfgPtr; /**< The cipher core config */ + u32 IsReady; /**< The ready flag */ + XHdcp1x_Cipher Cipher; /**< The interface's cipher */ + XHdcp1x_Port Port; /**< The interface's port */ +} XHdcp1x_Common; + +/** +* This typedef contains the transmit HDCP interface +*/ +typedef struct { + const XHdcp1x_Config *CfgPtr; /**< The cipher core config */ + u32 IsReady; /**< The ready flag */ + XHdcp1x_Cipher Cipher; /**< The interface's cipher */ + XHdcp1x_Port Port; /**< The interface's port */ + u32 CurrentState; /**< The interface's current state */ + u32 PreviousState; /**< The interface's previous state */ + u64 StateHelper; /**< The interface's state helper */ + u16 Flags; /**< The interface flags */ + u16 PendingEvents; /**< The bit map of pending events */ + u64 EncryptionMap; /**< The configured encryption map */ + XHdcp1x_TxStats Stats; /**< The interface's statistics */ +} XHdcp1x_Tx; + +/** +* This typedef contains the receive HDCP interface +*/ +typedef struct { + const XHdcp1x_Config *CfgPtr; /**< The cipher core config */ + u32 IsReady; /**< The ready flag */ + XHdcp1x_Cipher Cipher; /**< The interface's cipher */ + XHdcp1x_Port Port; /**< The interface's port */ + u32 CurrentState; /**< The interface's current state */ + u32 PreviousState; /**< The interface's previous state */ + u16 Flags; /**< The interface flags */ + u16 PendingEvents; /**< The bit map of pending events */ + XHdcp1x_RxStats Stats; /**< The interface's statistics */ +} XHdcp1x_Rx; + +/** +* This typedef contains an instance of an HDCP interface +*/ +typedef union { + XHdcp1x_Common Common; /**< The common interface elements */ + XHdcp1x_Tx Tx; /**< The transmit interface elements */ + XHdcp1x_Rx Rx; /**< The receive interface elements */ +} XHdcp1x; + +/** + * This typedef defines the function interface that is to be used for checking + * a specific KSV against the platforms revocation list + */ +typedef int (*XHdcp1x_KsvRevokeCheck)(const XHdcp1x *InstancePtr, u64 Ksv); + +/** + * This typedef defines the function interface that is to be used for starting + * a one shot timer on behalf of an HDCP interface within the underlying + * platform + */ +typedef int (*XHdcp1x_TimerStart)(const XHdcp1x *InstancePtr, u16 TmoInMs); + +/** + * This typedef defines the function interface that is to be used for stopping + * a timer on behalf of an HDCP interface + */ +typedef int (*XHdcp1x_TimerStop)(const XHdcp1x *InstancePtr); + +/** + * This typedef defines the function interface that is to be used for + * performing a busy delay on behalf of an HDCP interface + */ +typedef int (*XHdcp1x_TimerDelay)(const XHdcp1x *InstancePtr, u16 DelayInMs); + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +XHdcp1x_Config *XHdcp1x_LookupConfig(u16 DeviceId); + +int XHdcp1x_CfgInitialize(XHdcp1x *InstancePtr, const XHdcp1x_Config *CfgPtr, + void *PhyIfPtr); + +int XHdcp1x_SelfTest(XHdcp1x *InstancePtr); + +int XHdcp1x_Poll(XHdcp1x *InstancePtr); + +int XHdcp1x_Reset(XHdcp1x *InstancePtr); +int XHdcp1x_Enable(XHdcp1x *InstancePtr); +int XHdcp1x_Disable(XHdcp1x *InstancePtr); + +int XHdcp1x_SetPhysicalState(XHdcp1x *InstancePtr, int IsUp); +int XHdcp1x_SetLaneCount(XHdcp1x *InstancePtr, int LaneCount); + +int XHdcp1x_Authenticate(XHdcp1x *InstancePtr); +int XHdcp1x_IsInProgress(const XHdcp1x *InstancePtr); +int XHdcp1x_IsAuthenticated(const XHdcp1x *InstancePtr); + +u64 XHdcp1x_GetEncryption(const XHdcp1x *InstancePtr); +int XHdcp1x_EnableEncryption(XHdcp1x *InstancePtr, u64 StreamMap); +int XHdcp1x_DisableEncryption(XHdcp1x *InstancePtr, u64 StreamMap); + +int XHdcp1x_SetKeySelect(XHdcp1x *InstancePtr, u8 KeySelect); + +void XHdcp1x_HandleTimeout(void *InstancePtr); +void XHdcp1x_CipherIntrHandler(void *InstancePtr); +void XHdcp1x_PortIntrHandler(void *InstancePtr, u32 IntCause); + +void XHdcp1x_SetDebugPrintf(XHdcp1x_Printf PrintfFunc); +void XHdcp1x_SetDebugLogMsg(XHdcp1x_LogMsg LogFunc); + +void XHdcp1x_SetKsvRevokeCheck(XHdcp1x_KsvRevokeCheck RevokeCheckFunc); +void XHdcp1x_SetTimerStart(XHdcp1x_TimerStart TimerStartFunc); +void XHdcp1x_SetTimerStop(XHdcp1x_TimerStop TimerStopFunc); +void XHdcp1x_SetTimerDelay(XHdcp1x_TimerDelay TimerDelayFunc); + +u32 XHdcp1x_GetDriverVersion(void); +u32 XHdcp1x_GetVersion(const XHdcp1x *InstancePtr); +void XHdcp1x_Info(const XHdcp1x *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* XHDCP1X_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher.c new file mode 100644 index 00000000..bbb375dd --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher.c @@ -0,0 +1,1479 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_cipher.c +* +* This file contains the main implementation of the driver associated with +* the Xilinx HDCP Cipher core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "xhdcp1x.h" +#include "xhdcp1x_cipher_hw.h" +#include "xhdcp1x_cipher.h" +#include "xil_assert.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This function performs register read from a cipher +* +* @param InstancePtr the instance to read from +* @param Reg the register to read +* +* @return +* The current contents of the indicated register +* +* @note +* None. +* +******************************************************************************/ +#define RegRead(InstancePtr, Reg) \ + XHdcp1x_CipherReadReg(InstancePtr->CfgPtr->BaseAddress, Reg) + +/*****************************************************************************/ +/** +* +* This function performs register write to a cipher +* +* @param InstancePtr the instance to write to +* @param Reg the register to write +* @param Value the value to write +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +#define RegWrite(InstancePtr, Reg, Value) \ + XHdcp1x_CipherWriteReg(InstancePtr->CfgPtr->BaseAddress, Reg, Value) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if it is Display Port (DP) +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating DP (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsDP(InstancePtr) \ + XHdcp1x_CipherIsDP(InstancePtr) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if it is HDMI +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating HDMI (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsHDMI(InstancePtr) \ + XHdcp1x_CipherIsHDMI(InstancePtr) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if it is a receiver +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating receiver (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsRX(InstancePtr) \ + XHdcp1x_CipherIsRX(InstancePtr) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if it is a transmitter +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating transmitter (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsTX(InstancePtr) \ + XHdcp1x_CipherIsTX(InstancePtr) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if it is enabled +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating transmitter (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsEnabled(InstancePtr) \ + ((RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL) & \ + XHDCP1X_CIPHER_BITMASK_CONTROL_ENABLE) != 0) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if the XOR (encryption) function is +* currently in progress +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating in progress (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define XorInProgress(InstancePtr) \ + ((RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_STATUS) & \ + XHDCP1X_CIPHER_BITMASK_CIPHER_STATUS_XOR_IN_PROG) != 0) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if the local KSV is ready to read +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating ready (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define LocalKsvReady(InstancePtr) \ + ((RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_STATUS) & \ + XHDCP1X_CIPHER_BITMASK_KEYMGMT_STATUS_KSV_READY) != 0) + +/*****************************************************************************/ +/** +* +* This queries a cipher to determine if the Km value is ready +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating ready (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define KmReady(InstancePtr) \ + ((RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_STATUS) & \ + XHDCP1X_CIPHER_BITMASK_KEYMGMT_STATUS_Km_READY) != 0) + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function enables a hdcp cipher +* +* @param InstancePtr the device to enable +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Enable(XHdcp1x_Cipher* InstancePtr) +{ + u32 Value = 0; + + /* Clear the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Ensure that all encryption is disabled for now */ + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, 0x00ul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, 0x00ul); + + /* Ensure that XOR is disabled on tx and enabled for rx to start */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE; + if (IsRX(InstancePtr)) { + Value |= XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE; + } + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value); + + /* Enable it */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_ENABLE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Ensure that the register update bit is set */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + return; +} + +/*****************************************************************************/ +/** +* +* This function disables a hdcp cipher +* +* @param InstancePtr the device to disable +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Disable(XHdcp1x_Cipher* InstancePtr) +{ + u32 Value = 0; + + /* Ensure all interrupts are disabled */ + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_MASK, 0xFFFFFFFFul); + + /* Enable bypass operation */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_ENABLE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Ensure that all encryption is disabled for now */ + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, 0x00ul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, 0x00ul); + + /* Ensure that XOR is disabled */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value); + + /* Ensure that the register update bit is set */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Wait until the XOR has actually stopped */ + while (XorInProgress(InstancePtr)); + + return; +} + +/*****************************************************************************/ +/** +* +* This function initializes a hdcp cipher +* +* @param InstancePtr the device to initialize +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Init(XHdcp1x_Cipher* InstancePtr) +{ + u32 Value = 0; + + /* Reset it */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_RESET; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_RESET; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Ensure all interrupts are disabled and cleared */ + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_MASK, (u32) (-1)); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_STATUS, (u32) (-1)); + + /* Check for DP */ + if (IsDP(InstancePtr)) { + + /* Configure for four lanes SST */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES; + Value |= (4u << 4); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + } + + /* Ensure that the register update bit is set */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + return; +} + +/*****************************************************************************/ +/** +* +* This function initializes a cipher device +* +* @param InstancePtr the device to initialize +* @param CfgPtr the device configuration +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherCfgInitialize(XHdcp1x_Cipher* InstancePtr, + const XHdcp1x_Config* CfgPtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady != XIL_COMPONENT_IS_READY); + + /* Initialize InstancePtr */ + memset(InstancePtr, 0, sizeof(XHdcp1x_Cipher)); + InstancePtr->CfgPtr = CfgPtr; + + /* Check for mismatch on direction */ + if (IsRX(InstancePtr)) { + if (!(CfgPtr->IsRx)) { + Status = XST_FAILURE; + } + } + else if (CfgPtr->IsRx) { + Status = XST_FAILURE; + } + + /* Check for mismatch on protocol */ + if (IsHDMI(InstancePtr)) { + if (!(CfgPtr->IsHDMI)) { + Status = XST_FAILURE; + } + } + else if (CfgPtr->IsHDMI) { + Status = XST_FAILURE; + } + + /* Initialize it */ + if (Status == XST_SUCCESS) { + Init(InstancePtr); + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function queries the link state of a cipher device +* +* @param InstancePtr the device to query +* +* @return +* Truth value +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherIsLinkUp(const XHdcp1x_Cipher* InstancePtr) +{ + int isUp = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check for currently enabled */ + if (IsEnabled(InstancePtr)) { + + u32 Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_STATUS); + if ((Value & XHDCP1X_CIPHER_BITMASK_INTERRUPT_LINK_FAIL) != 0) + isUp = TRUE; + } + + return (isUp); +} + +/*****************************************************************************/ +/** +* +* This function enables a hdcp cipher +* +* @param InstancePtr the device to enable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherEnable(XHdcp1x_Cipher* InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check for currently disabled */ + if (!IsEnabled(InstancePtr)) { + Enable(InstancePtr); + } + else { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables a hdcp cipher +* +* @param InstancePtr the device to disable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherDisable(XHdcp1x_Cipher* InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check for currently enabled */ + if (IsEnabled(InstancePtr)) { + Disable(InstancePtr); + } + + /* Return */ + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function configures the key selection value +* +* @param InstancePtr the device to configure +* @param KeySelect the desired key select value +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherSetKeySelect(XHdcp1x_Cipher* InstancePtr, u8 KeySelect) +{ + int Status = XST_SUCCESS; + u32 Value = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(KeySelect < 8); + + /* Update the device */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_SET_SELECT; + Value |= (KeySelect << 16); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Value); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function initiates a request within the hdcp cipher +* +* @param InstancePtr the device to submit the request to +* @param Request the request to submit +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherDoRequest(XHdcp1x_Cipher* InstancePtr, + XHdcp1x_CipherRequestType Request) +{ + u32 Value = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Request >= (XHDCP1X_CIPHER_REQUEST_BLOCK)); +// Xil_AssertNonvoid(Request < (XHDCP1X_CIPHER_REQUEST_MAX)); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Determine if there is a request in progress */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_STATUS); + Value &= XHDCP1X_CIPHER_BITMASK_CIPHER_STATUS_REQUEST_IN_PROG; + + /* Check that it is not busy */ + if (Value != 0) { + return (XST_DEVICE_BUSY); + } + + /* Ensure that the register update bit is set */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Set the appropriate request bit and ensure that Km is always used */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_REQUEST; + Value |= (XHDCP1X_CIPHER_VALUE_CIPHER_CONTROL_REQUEST_BLOCK<>= 4; + } + + /* Return */ + return (NumLanes); +} + +/*****************************************************************************/ +/** +* +* This function configures the number of lanes of the hdcp cipher +* +* @param InstancePtr the device to configure +* @param NumLanes the number of lanes to configure +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherSetNumLanes(XHdcp1x_Cipher* InstancePtr, u32 NumLanes) +{ + int Status = XST_SUCCESS; + u32 Value = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(NumLanes > 0); + Xil_AssertNonvoid(NumLanes <= 4); + + /* Check for HDMI */ + if (IsHDMI(InstancePtr)) { + + /* Verify NumLanes (again) */ + Xil_AssertNonvoid(NumLanes == 1); + + /* Update the control register */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES; + Value |= (NumLanes << 4); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + } + /* Otherwise - must be DP */ + else { + + /* Verify NumLanes (again) */ + Xil_AssertNonvoid(NumLanes != 3); + + /* Update the control register */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES; + Value |= (NumLanes << 4); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the current encryption stream map +* +* @param InstancePtr the device to query +* +* @return +* The current encryption stream map. +* +* @note +* In the case of the receiver version of this core, the XOR in progress bit +* needs to be checked as well as the encryption map to fully determine if +* encryption is enabled for the SST case. This is reason for the additional +* check in this code +* +******************************************************************************/ +u64 XHdcp1x_CipherGetEncryption(const XHdcp1x_Cipher* InstancePtr) +{ + u64 StreamMap = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (StreamMap); + } + + /* Determine StreamMap */ + StreamMap = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H); + StreamMap <<= 32; + StreamMap |= RegRead(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L); + + /* Check for special case of just XOR in progress */ + if ((StreamMap == 0) && (XorInProgress(InstancePtr))) { + StreamMap = 0x01ul; + } + + return (StreamMap); +} + +/*****************************************************************************/ +/** +* +* This function enables encryption on a set of streams +* +* @param InstancePtr the device to configure +* @param StreamMap the bit map of streams to enable encryption on +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherEnableEncryption(XHdcp1x_Cipher* InstancePtr, u64 StreamMap) +{ + u32 Value = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Check that it is not a receiver */ + if (IsRX(InstancePtr)) { + return (XST_FAILURE); + } + + /* Check for nothing to do */ + if (StreamMap == 0) { + return (XST_SUCCESS); + } + + /* Clear the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Update the LS 32-bits */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L); + Value |= ((u32) (StreamMap & 0xFFFFFFFFul)); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, Value); + + /* Write the MS 32-bits */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H); + Value |= ((u32) ((StreamMap >> 32) & 0xFFFFFFFFul)); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, Value); + + /* Ensure that the XOR is enabled */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Value); + + /* Set the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Wait until the XOR has actually started */ + while (!XorInProgress(InstancePtr)); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function disables encryption on a set of streams +* +* @param InstancePtr the device to configure +* @param StreamMap the bit map of streams to disable encryption on +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherDisableEncryption(XHdcp1x_Cipher* InstancePtr, u64 StreamMap) +{ + u32 Val = 0; + int DisableXor = TRUE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Check that it is not a receiver */ + if (IsRX(InstancePtr)) { + return (XST_FAILURE); + } + + /* Check for nothing to do */ + if (StreamMap == 0) { + return (XST_SUCCESS); + } + + /* Clear the register update bit */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Val &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Val); + + /* Update the LS 32-bits */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L); + Val &= ~((u32) (StreamMap & 0xFFFFFFFFul)); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L, Val); + if (Val != 0) { + DisableXor = FALSE; + } + + /* Write the MS 32-bits */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H); + Val &= ~((u32) ((StreamMap >> 32) & 0xFFFFFFFFul)); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H, Val); + if (Val != 0) { + DisableXor = FALSE; + } + + /* Check HDMI special case */ + if (IsHDMI(InstancePtr)) { + DisableXor = TRUE; + } + + /* Check for XOR disable */ + if (DisableXor) { + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL); + Val &= ~XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_CONTROL, Val); + } + + /* Set the register update bit */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Val |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Val); + + /* If disabling the XOR, wait until no longer in progress */ + if (DisableXor) { + while (XorInProgress(InstancePtr)); + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function reads the local KSV value from the cipher +* +* @param InstancePtr the device to query +* + * @return +* The local KSV value +* +* @note +* None. +* +******************************************************************************/ +u64 XHdcp1x_CipherGetLocalKsv(const XHdcp1x_Cipher* InstancePtr) +{ + u32 Val = 0; + u32 Guard = 0x400ul; + u64 Ksv = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (Ksv); + } + + /* Check if the local ksv is not available */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_STATUS); + Val &= XHDCP1X_CIPHER_BITMASK_KEYMGMT_STATUS_KSV_READY; + if (Val == 0) { + + /* Abort any running Km calculation just in case */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL); + Val |= XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_ABORT_Km; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val); + Val &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_ABORT_Km; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val); + + /* Load the local ksv */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL); + Val |= XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_LOCAL_KSV; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val); + Val &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_LOCAL_KSV; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Val); + + /* Wait until local KSV available */ + while ((!LocalKsvReady(InstancePtr)) && (--Guard > 0)); + } + + /* Confirm no timeout */ + if (Guard != 0) { + + /* Update Ksv */ + Ksv = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KSV_LOCAL_H); + Ksv &= 0xFFul; + Ksv <<= 32; + Ksv |= RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KSV_LOCAL_L); + } + + return (Ksv); +} + +/*****************************************************************************/ +/** +* +* This function reads the remote KSV value from the cipher +* +* @param InstancePtr the device to query +* +* @return +* The remote KSV value +* +* @note +* None. +* +******************************************************************************/ +u64 XHdcp1x_CipherGetRemoteKsv(const XHdcp1x_Cipher* InstancePtr) +{ + /* Locals */ + u64 Ksv = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Ksv */ + Ksv = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KSV_REMOTE_H); + Ksv <<= 32; + Ksv |= RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KSV_REMOTE_L); + + /* Return */ + return (Ksv); +} + +/*****************************************************************************/ +/** +* +* This function writes the remote KSV value to the cipher +* +* @param InstancePtr the device to write to +* @param Ksv the remote KSV value to write +* +* @return +* XST_SUCCESS if successful. +* +* @note +* Whenever this function is called, the underlying driver will initiate +* the calculation of the Km value and wait for it to complete. +* +******************************************************************************/ +int XHdcp1x_CipherSetRemoteKsv(XHdcp1x_Cipher* InstancePtr, u64 Ksv) +{ + u32 Value = 0; + u32 Guard = 0x400ul; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Read local ksv to put things into a known state */ + XHdcp1x_CipherGetLocalKsv(InstancePtr); + + /* Clear the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Write the LS 32-bits */ + Value = (u32) (Ksv & 0xFFFFFFFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KSV_REMOTE_L, Value); + + /* Write the MS 8-bits */ + Value = (u32) ((Ksv >> 32) & 0xFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KSV_REMOTE_H, Value); + + /* Set the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Trigger the calculation of theKm */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL); + Value &= 0xFFFFFFF0ul; + Value |= XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_BEGIN_Km; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Value); + Value &= ~XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_BEGIN_Km; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL, Value); + + /* Wait until Km is available */ + while ((!KmReady(InstancePtr)) && (--Guard > 0)); + + /* Check for timeout */ + if (Guard == 0) { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ + +/** +* +* This function reads the contents of the B register in BM0 +* +* @param InstancePtr the device to query +* @param X to be loaded with the contents of Bx +* @param Y to be loaded with the contents of By +* @param Z to be loaded with the contents of Bz +* +* @return +* XST_SUCCESS if successful. +* +* @note +* A NULL pointer can be passed in any of X, Y and Z. If so, then +* this portion of the B register is not returned to the caller. +* +******************************************************************************/ +int XHdcp1x_CipherGetB(const XHdcp1x_Cipher* InstancePtr, u32* X, u32* Y, + u32* Z) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Get X if requested */ + if (X != NULL) { + *X = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Bx); + *X &= 0x0FFFFFFFul; + } + + /* Get Y if requested */ + if (Y != NULL) { + *Y = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_By); + *Y &= 0x0FFFFFFFul; + } + + /* Get Z if requested */ + if (Z != NULL) { + *Z = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Bz); + *Z &= 0x0FFFFFFFul; + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function writes the contents of the B register in BM0 +* +* @param InstancePtr the device to write to +* @param X the value to be written to Bx +* @param Y the value to be written to By +* @param Z the value to be written to Bz +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None +* +******************************************************************************/ +int XHdcp1x_CipherSetB(XHdcp1x_Cipher* InstancePtr, u32 X, u32 Y, u32 Z) +{ + u32 Value = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Clear the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Update the Bx */ + Value = (X & 0x0FFFFFFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Bx, Value); + + /* Update the By */ + Value = (Y & 0x0FFFFFFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_By, Value); + + /* Update the Bz */ + Value = (Z & 0x0FFFFFFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Bz, Value); + + /* Set the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function reads the contents of the K register in BM0 +* +* @param InstancePtr the device to query +* @param X to be loaded with the contents of Kx +* @param Y to be loaded with the contents of Ky +* @param Z to be loaded with the contents of Kz +* +* @return +* XST_SUCCESS if successful. +* +* @note +* A NULL pointer can be passed in any of X, Y and Z. If so, then +* this portion of the K register is not returned to the caller. +* +******************************************************************************/ +int XHdcp1x_CipherGetK(const XHdcp1x_Cipher* InstancePtr, u32* X, u32* Y, + u32* Z) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Get X if requested */ + if (X != NULL) { + *X = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Kx); + *X &= 0x0FFFFFFFul; + } + + /* Get Y if requested */ + if (Y != NULL) { + *Y = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Ky); + *Y &= 0x0FFFFFFFul; + } + + /* Get Z if requested */ + if (Z != NULL) { + *Z = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Kz); + *Z &= 0x0FFFFFFFul; + } + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function writes the contents of the K register in BM0 +* +* @param InstancePtr the device to write to +* @param X the value to be written to Kx +* @param Y the value to be written to Ky +* @param Z the value to be written to Kz +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None +* +******************************************************************************/ +int XHdcp1x_CipherSetK(XHdcp1x_Cipher* InstancePtr, u32 X, u32 Y, u32 Z) +{ + u32 Value = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Clear the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value &= ~XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + /* Update the Kx */ + Value = (X & 0x0FFFFFFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Kx, Value); + + /* Update the Ky */ + Value = (Y & 0x0FFFFFFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Ky, Value); + + /* Update the Kz */ + Value = (Z & 0x0FFFFFFFul); + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Kz, Value); + + /* Set the register update bit */ + Value = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL); + Value |= XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE; + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_CONTROL, Value); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function reads the contents of the Mi/An register of BM0 +* +* @param InstancePtr the device to query +* +* @return +* The contents of the register +* +* @note +* None +* +******************************************************************************/ +u64 XHdcp1x_CipherGetMi(const XHdcp1x_Cipher* InstancePtr) +{ + u64 Mi = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Update Mi */ + Mi = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Mi_H); + Mi <<= 32; + Mi |= RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Mi_L); + + return (Mi); +} + +/*****************************************************************************/ +/** +* +* This function reads the contents of the Ri register of BM0 +* +* @param InstancePtr the device to query +* +* @return +* The contents of the register +* +* @note +* None +* +******************************************************************************/ +u16 XHdcp1x_CipherGetRi(const XHdcp1x_Cipher* InstancePtr) +{ + u16 Ri = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Determine theRi */ + Ri = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Ri); + + return (Ri); +} + +/*****************************************************************************/ +/** +* +* This function reads the contents of the Mo register of the device +* +* @param InstancePtr the device to query +* +* @return +* The contents of the Mo register +* +* @note +* None +* +******************************************************************************/ +u64 XHdcp1x_CipherGetMo(const XHdcp1x_Cipher* InstancePtr) +{ + u64 Mo = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Determine Mo */ + Mo = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Mo_H); + Mo <<= 32; + Mo |= RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Mo_L); + + return (Mo); +} + +/*****************************************************************************/ +/** +* +* This function reads the contents of the Ro register of the device +* +* @param InstancePtr the device to query +* +* @return +* The contents of the Ro register +* +* @note +* None +* +******************************************************************************/ +u16 XHdcp1x_CipherGetRo(const XHdcp1x_Cipher* InstancePtr) +{ + u16 Ro = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check that it is not disabled */ + if (!IsEnabled(InstancePtr)) { + return (XST_NOT_ENABLED); + } + + /* Determine Ro */ + Ro = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_CIPHER_Ro); + + return (Ro); +} + +/*****************************************************************************/ +/** +* +* This function reads the version of the hdcp cipher core +* +* @param InstancePtr the device to query +* +* @return +* The version of the hdcp cipher device +* +* @note +* None +* +******************************************************************************/ +u32 XHdcp1x_CipherGetVersion(const XHdcp1x_Cipher* InstancePtr) +{ + u32 Version = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Version */ + Version = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_VERSION); + + return (Version); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher.h new file mode 100644 index 00000000..e5fd4904 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher.h @@ -0,0 +1,216 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_cipher.h +* +* This is the main header file for Xilinx HDCP Cipher core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ +#ifndef XHDCP1X_CIPHER_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_CIPHER_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xhdcp1x_cipher_hw.h" +#include "xstatus.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/** @name Handler Types +* @{ +*/ +/** +* These constants specify different types of handler and used to differentiate +* interrupt requests from peripheral. +*/ +typedef enum { + XHDCP1X_CIPHER_HANDLER_LINK_FAILURE = 1, + XHDCP1X_CIPHER_HANDLER_Ri_UPDATE, +} XHdcp1x_CipherHandlerType; +/*@}*/ + + +/** @name Request Types +* @{ +*/ +/** +* These constants specify different types of authentication requests that +* can be initiated within a peripheral +*/ +typedef enum { + XHDCP1X_CIPHER_REQUEST_BLOCK, + XHDCP1X_CIPHER_REQUEST_REKEY, + XHDCP1X_CIPHER_REQUEST_RNG, + XHDCP1X_CIPHER_REQUEST_MAX, +} XHdcp1x_CipherRequestType; +/*@}*/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This macro checks if a core supports the Display Port protocol +* +* @param InstancePtr is a pointer to the XHdcp1x_Cipher core instance. +* +* @return Truth value indicating DP (TRUE) or not (FALSE) +* +******************************************************************************/ +#define XHdcp1x_CipherIsDP(InstancePtr) \ + ((XHdcp1x_CipherReadReg((InstancePtr->CfgPtr)->BaseAddress, \ + XHDCP1X_CIPHER_REG_TYPE) & XHDCP1X_CIPHER_BITMASK_TYPE_PROTOCOL) \ + == XHDCP1X_CIPHER_VALUE_TYPE_PROTOCOL_DP) + +/*****************************************************************************/ +/** +* +* This macro checks if a core supports the HDMI protocol +* +* @param InstancePtr is a pointer to the XHdcp1x_Cipher core instance. +* +* @return Truth value indicating HDMI (TRUE) or not (FALSE) +* +******************************************************************************/ +#define XHdcp1x_CipherIsHDMI(InstancePtr) \ + ((XHdcp1x_CipherReadReg((InstancePtr->CfgPtr)->BaseAddress, \ + XHDCP1X_CIPHER_REG_TYPE) & XHDCP1X_CIPHER_BITMASK_TYPE_PROTOCOL) \ + == XHDCP1X_CIPHER_VALUE_TYPE_PROTOCOL_HDMI) + +/*****************************************************************************/ +/** +* +* This macro checks if a core supports the receive direction +* +* @param InstancePtr is a pointer to the XHdcp1x_Cipher core instance. +* +* @return Truth value indicating receive (TRUE) or not (FALSE) +* +******************************************************************************/ +#define XHdcp1x_CipherIsRX(InstancePtr) \ + ((XHdcp1x_CipherReadReg((InstancePtr->CfgPtr)->BaseAddress, \ + XHDCP1X_CIPHER_REG_TYPE) & XHDCP1X_CIPHER_BITMASK_TYPE_DIRECTION) \ + == XHDCP1X_CIPHER_VALUE_TYPE_DIRECTION_RX) + +/*****************************************************************************/ +/** +* +* This macro checks if a core supports the transmit direction +* +* @param InstancePtr is a pointer to the XHdcp1x_Cipher core instance. +* +* @return Truth value indicating transmit (TRUE) or not (FALSE) +* +******************************************************************************/ +#define XHdcp1x_CipherIsTX(InstancePtr) \ + ((XHdcp1x_CipherReadReg((InstancePtr->CfgPtr)->BaseAddress, \ + XHDCP1X_CIPHER_REG_TYPE) & XHDCP1X_CIPHER_BITMASK_TYPE_DIRECTION) \ + == XHDCP1X_CIPHER_VALUE_TYPE_DIRECTION_TX) + + +/************************** Function Prototypes ******************************/ + +int XHdcp1x_CipherCfgInitialize(XHdcp1x_Cipher *InstancePtr, + const XHdcp1x_Config *CfgPtr); + +int XHdcp1x_CipherSetCallback(XHdcp1x_Cipher *InstancePtr, u32 HandlerType, + XHdcp1x_Callback Callback, void *Ref); + +int XHdcp1x_CipherSetLinkStateCheck(XHdcp1x_Cipher *InstancePtr, + int IsEnabled); +int XHdcp1x_CipherIsLinkUp(const XHdcp1x_Cipher *InstancePtr); +int XHdcp1x_CipherSetRiUpdate(XHdcp1x_Cipher *InstancePtr, int IsEnabled); + +int XHdcp1x_CipherEnable(XHdcp1x_Cipher *InstancePtr); +int XHdcp1x_CipherDisable(XHdcp1x_Cipher *InstancePtr); + +int XHdcp1x_CipherSetKeySelect(XHdcp1x_Cipher *InstancePtr, u8 KeySelect); + +int XHdcp1x_CipherDoRequest(XHdcp1x_Cipher *InstancePtr, + XHdcp1x_CipherRequestType Request); +int XHdcp1x_CipherIsRequestComplete(const XHdcp1x_Cipher *InstancePtr); + +u32 XHdcp1x_CipherGetNumLanes(const XHdcp1x_Cipher *InstancePtr); +int XHdcp1x_CipherSetNumLanes(XHdcp1x_Cipher *InstancePtr, u32 NumLanes); + +u64 XHdcp1x_CipherGetEncryption(const XHdcp1x_Cipher *InstancePtr); +int XHdcp1x_CipherEnableEncryption(XHdcp1x_Cipher *InstancePtr, + u64 StreamMap); +int XHdcp1x_CipherDisableEncryption(XHdcp1x_Cipher *InstancePtr, + u64 StreamMap); + +u64 XHdcp1x_CipherGetLocalKsv(const XHdcp1x_Cipher *InstancePtr); +u64 XHdcp1x_CipherGetRemoteKsv(const XHdcp1x_Cipher *InstancePtr); +int XHdcp1x_CipherSetRemoteKsv(XHdcp1x_Cipher *InstancePtr, u64 Ksv); + +int XHdcp1x_CipherGetB(const XHdcp1x_Cipher *InstancePtr, u32* X, u32* Y, + u32* Z); +int XHdcp1x_CipherSetB(XHdcp1x_Cipher *InstancePtr, u32 X, u32 Y, u32 Z); +int XHdcp1x_CipherGetK(const XHdcp1x_Cipher *InstancePtr, u32* X, u32* Y, + u32* Z); +int XHdcp1x_CipherSetK(XHdcp1x_Cipher *InstancePtr, u32 X, u32 Y, u32 Z); + +u64 XHdcp1x_CipherGetMi(const XHdcp1x_Cipher *InstancePtr); +u16 XHdcp1x_CipherGetRi(const XHdcp1x_Cipher *InstancePtr); +u64 XHdcp1x_CipherGetMo(const XHdcp1x_Cipher *InstancePtr); +u16 XHdcp1x_CipherGetRo(const XHdcp1x_Cipher *InstancePtr); + +u32 XHdcp1x_CipherGetVersion(const XHdcp1x_Cipher *InstancePtr); + +void XHdcp1x_CipherHandlerInterrupt(void *InstancePtr); + + +#ifdef __cplusplus +} +#endif + + +#endif /* XHDCP1X_CIPHER_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_hw.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_hw.h new file mode 100644 index 00000000..b146a764 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_hw.h @@ -0,0 +1,194 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_cipher_hw.h +* +* This header file contains identifiers and register-level core functions (or +* macros) that can be used to access the Xilinx HDCP cipher core. +* +* For more information about the operation of this core see the hardware +* specification and documentation in the higher level driver xhdcp1x_ciper.h +* file. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Fixed RNG cipher request value
+* 
+* + ******************************************************************************/ +#ifndef XHDCP1X_CIPHER_HW_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_CIPHER_HW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xil_io.h" + +/************************** Constant Definitions *****************************/ + +// HDCP Cipher register offsets +#define XHDCP1X_CIPHER_REG_VERSION (0x0000u) /**< Version register offset */ +#define XHDCP1X_CIPHER_REG_TYPE (0x0004u) /**< Type register offset */ +#define XHDCP1X_CIPHER_REG_SCRATCH (0x0008u) /**< Scratch pad register offset */ +#define XHDCP1X_CIPHER_REG_CONTROL (0x000Cu) /**< Control register offset */ +#define XHDCP1X_CIPHER_REG_STATUS (0x0010u) /**< Status register offset */ +#define XHDCP1X_CIPHER_REG_INTERRUPT_MASK (0x0014u) /**< Interrupt Mask register offset */ +#define XHDCP1X_CIPHER_REG_INTERRUPT_STATUS (0x0018u) /**< Interrupt Status register offset */ +#define XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_H (0x0020u) /**< Encryption Enable (High) register offset */ +#define XHDCP1X_CIPHER_REG_ENCRYPT_ENABLE_L (0x0024u) /**< Encryption Enable (Low) register offset */ + +#define XHDCP1X_CIPHER_REG_KEYMGMT_CONTROL (0x002Cu) /**< Key Management Control register offset */ +#define XHDCP1X_CIPHER_REG_KEYMGMT_STATUS (0x0030u) /**< Key Management Status register offset */ +#define XHDCP1X_CIPHER_REG_KSV_LOCAL_H (0x0038u) /**< Local KSV (High) register offset */ +#define XHDCP1X_CIPHER_REG_KSV_LOCAL_L (0x003Cu) /**< Local KSV (Low) register offset */ +#define XHDCP1X_CIPHER_REG_KSV_REMOTE_H (0x0040u) /**< Remote KSV (High) offset */ +#define XHDCP1X_CIPHER_REG_KSV_REMOTE_L (0x0044u) /**< Remote KSV (Low) register offset */ +#define XHDCP1X_CIPHER_REG_Km_H (0x0048u) /**< Km (High) register offset */ +#define XHDCP1X_CIPHER_REG_Km_L (0x004Cu) /**< Km (Low) register offset */ + +#define XHDCP1X_CIPHER_REG_CIPHER_CONTROL (0x0050u) /**< Cipher Control register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_STATUS (0x0054u) /**< Cipher Status register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Bx (0x0058u) /**< Cipher Bx register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_By (0x005Cu) /**< Cipher By register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Bz (0x0060u) /**< Cipher Bz register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Kx (0x0064u) /**< Cipher Kx register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Ky (0x0068u) /**< Cipher Ky register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Kz (0x006Cu) /**< Cipher Kz register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Mi_H (0x0070u) /**< Cipher Mi (High) register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Mi_L (0x0074u) /**< Cipher Mi (Low) register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Ri (0x0078u) /**< Cipher Ri register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Ro (0x007Cu) /**< Cipher Ro register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Mo_H (0x0080u) /**< Cipher Mo (High) register offset */ +#define XHDCP1X_CIPHER_REG_CIPHER_Mo_L (0x0084u) /**< Cipher Mo (Low) register offset */ + +// HDCP Cipher register bit mask definitions +#define XHDCP1X_CIPHER_BITMASK_TYPE_PROTOCOL (0x03u << 0) /**< Protocol bitmask in Type register */ +#define XHDCP1X_CIPHER_BITMASK_TYPE_DIRECTION (0x01u << 2) /**< Direction bitmask in Type register */ + +#define XHDCP1X_CIPHER_BITMASK_CONTROL_ENABLE (0x01u << 0) /**< Enable bitmask in Control register */ +#define XHDCP1X_CIPHER_BITMASK_CONTROL_UPDATE (0x01u << 1) /**< Update bitmask in Control register */ +#define XHDCP1X_CIPHER_BITMASK_CONTROL_NUM_LANES (0x07u << 4) /**< Num Lanes bitmask in Control register */ +#define XHDCP1X_CIPHER_BITMASK_CONTROL_RESET (0x01u << 31) /**< Reset bitmask in Control register */ + +#define XHDCP1X_CIPHER_BITMASK_INTERRUPT_LINK_FAIL (0x01u << 0) /**< Link Failure bitmask in Interrupt register(s) */ +#define XHDCP1X_CIPHER_BITMASK_INTERRUPT_Ri_UPDATE (0x01u << 1) /**< Ri bitmask in Interrupt register(s) */ + +#define XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_LOCAL_KSV (0x01u << 0) /**< Read Local KSV bitmask in Key Management Control register */ +#define XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_BEGIN_Km (0x01u << 1) /**< Being Km bitmask in Key Management Control register */ +#define XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_ABORT_Km (0x01u << 2) /**< Abort Km bitmask in Key Management Control register */ +#define XHDCP1X_CIPHER_BITMASK_KEYMGMT_CONTROL_SET_SELECT (0x07u << 16) /**< Key Set Select bitmask in Key Management Control register */ + +#define XHDCP1X_CIPHER_BITMASK_KEYMGMT_STATUS_KSV_READY (0x01u << 0) /**< Local KSV ready bitmask in Key Management Status register */ +#define XHDCP1X_CIPHER_BITMASK_KEYMGMT_STATUS_Km_READY (0x01u << 1) /**< Km Value ready bitmask in Key Management Status register */ + +#define XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_XOR_ENABLE (0x01u << 0) /**< XOR Enable bitmask in Cipher Control register */ +#define XHDCP1X_CIPHER_BITMASK_CIPHER_CONTROL_REQUEST (0x07u << 8) /**< Request bitmask in Cipher Control register */ + +#define XHDCP1X_CIPHER_BITMASK_CIPHER_STATUS_XOR_IN_PROG (0x01u << 0) /**< XOR In Progress bitmask in Cipher Status register */ +#define XHDCP1X_CIPHER_BITMASK_CIPHER_STATUS_REQUEST_IN_PROG (0x07u << 8) /**< Request In Progress bitmask in Cipher Status register */ + +// HDCP Cipher register bit value definitions +#define XHDCP1X_CIPHER_VALUE_TYPE_PROTOCOL_DP (0x00u << 0) /**< DP Protocol value in Type register */ +#define XHDCP1X_CIPHER_VALUE_TYPE_PROTOCOL_HDMI (0x01u << 0) /**< HDMI Protocol value in Type register */ + +#define XHDCP1X_CIPHER_VALUE_TYPE_DIRECTION_RX (0x00u << 2) /**< RX Direction value in Type register */ +#define XHDCP1X_CIPHER_VALUE_TYPE_DIRECTION_TX (0x01u << 2) /**< TX Direction value in Type register */ + +#define XHDCP1X_CIPHER_VALUE_CIPHER_CONTROL_REQUEST_BLOCK (0x01u << 8) /**< Block Request value in Cipher Control register */ +#define XHDCP1X_CIPHER_VALUE_CIPHER_CONTROL_REQUEST_REKEY (0x01u << 9) /**< ReKey Request value in Cipher Control register */ +#define XHDCP1X_CIPHER_VALUE_CIPHER_CONTROL_REQUEST_RNG (0x01u << 10) /**< RNG Request value in Cipher Control register */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +// Register access macro definition +#define XHdcp1x_CipherIn32 Xil_In32 /**< Input Operations */ +#define XHdcp1x_CipherOut32 Xil_Out32 /**< Output Operations */ + +/*****************************************************************************/ +/** +* +* This macro reads a value from a HDCP cipher register. A 32 bit read is +* always performed. +* +* @param BaseAddress is the base address of the HDCP cipher core instance. +* @param RegOffset is the register offset of the register +* +* @return +* The 32-bit value of the register. +* +* @note +* C-style: u32 XHdcp1x_CipherReadReg(u32 BaseAddress, u32 RegOffset) +* +******************************************************************************/ +#define XHdcp1x_CipherReadReg(BaseAddress, RegOffset) \ + XHdcp1x_CipherIn32((BaseAddress) + ((u32)RegOffset)) + +/*****************************************************************************/ +/** +* +* This macro writes a value to a HDCP cipher register. A 32 bit write is +* always performed. +* +* @param BaseAddress is the base address of the HDCP cipher core instance. +* @param RegOffset is the register offset of the register +* @param Data is the 32-bit value to write into the register. +* +* @return +* None. +* +* @note +* C-style: void XHdcp1x_CipherWriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) +* +******************************************************************************/ +#define XHdcp1x_CipherWriteReg(BaseAddress, RegOffset, Data) \ + XHdcp1x_CipherOut32((BaseAddress) + ((u32)RegOffset), (u32)(Data)) + +/************************** Function Prototypes ******************************/ + +/************************** Variable Declarations ****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XHDCP1X_CIPHER_HW_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_intr.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_intr.c new file mode 100644 index 00000000..1a3bfd69 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_intr.c @@ -0,0 +1,288 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_cipher_intr.c +* +* This file contains interrupt related functions for Xilinx HDCP core. +* Please see xhdcp1x_cipher.h for more details of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xhdcp1x_cipher_hw.h" +#include "xhdcp1x_cipher.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define RegRead(InstancePtr, Offset) \ + XHdcp1x_CipherReadReg(InstancePtr->CfgPtr->BaseAddress, Offset) + +#define RegWrite(InstancePtr, Offset, Value) \ + XHdcp1x_CipherWriteReg(InstancePtr->CfgPtr->BaseAddress, Offset, Value) + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function installs an asynchronous callback function for the given +* HandlerType: +* +*
+* HandlerType                             Callback Function Type
+* ------------------------------------    ------------------------------------
+* (XHDCP1X_CIPHER_HANDLER_LINK_FAILURE)   LinkFailCallback
+* (XHDCP1X_CIPHER_HANDLER_Ri_UPDATE)      RiUpdateCallback
+* 
+* +* @param InstancePtr is a pointer to the HDCP cipher core instance. +* @param HandlerType specifies the type of handler. +* @param CallbackFunc is the address of the callback function. +* @param CallbackRef is a user data item that will be passed to the +* callback function when it is invoked. +* +* @return +* - XST_SUCCESS if callback function installed successfully. +* - XST_INVALID_PARAM when HandlerType is invalid. +* +* @note Invoking this function for a handler that already has been +* installed replaces it with the new handler. +* +******************************************************************************/ +int XHdcp1x_CipherSetCallback(XHdcp1x_Cipher *InstancePtr, u32 HandlerType, + XHdcp1x_Callback CallbackFunc, void *CallbackRef) +{ + /* Locals */ + u32 Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(HandlerType >= XHDCP1X_CIPHER_HANDLER_LINK_FAILURE); + Xil_AssertNonvoid(CallbackFunc != NULL); + Xil_AssertNonvoid(CallbackRef != NULL); + + /* Check for handler type */ + switch (HandlerType) { + + /* Link Failure Callback */ + case (XHDCP1X_CIPHER_HANDLER_LINK_FAILURE): + InstancePtr->LinkFailCallback = CallbackFunc; + InstancePtr->LinkFailRef = CallbackRef; + InstancePtr->IsLinkFailCallbackSet = (TRUE); + break; + + /* Ri Update Callback */ + case (XHDCP1X_CIPHER_HANDLER_Ri_UPDATE): + InstancePtr->RiUpdateCallback = CallbackFunc; + InstancePtr->RiUpdateRef = CallbackRef; + InstancePtr->IsRiUpdateCallbackSet = (TRUE); + break; + + default: + Status = (XST_INVALID_PARAM); + break; + } + + /* Return */ + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function enables/disables the reporting of link check state changes +* +* @param InstancePtr the cipher core instance +* @param IsEnabled enable/disable link state change notifications +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherSetLinkStateCheck(XHdcp1x_Cipher *InstancePtr, int IsEnabled) +{ + int Status = XST_SUCCESS; + + /* Verify arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check DP receive */ + if (XHdcp1x_CipherIsDP(InstancePtr) && + XHdcp1x_CipherIsRX(InstancePtr)) { + + u32 Val = 0; + + /* Clear any pending link state failure interrupt */ + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_STATUS, + XHDCP1X_CIPHER_BITMASK_INTERRUPT_LINK_FAIL); + + /* Update it */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_MASK); + if (IsEnabled) { + Val &= ~XHDCP1X_CIPHER_BITMASK_INTERRUPT_LINK_FAIL; + } + else { + Val |= XHDCP1X_CIPHER_BITMASK_INTERRUPT_LINK_FAIL; + } + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_MASK, Val); + } + else { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function enables/disables the reporting of Ri update notifications +* +* @param InstancePtr the cipher core instance +* @param IsEnabled enable/disable Ri update notifications +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherSetRiUpdate(XHdcp1x_Cipher *InstancePtr, int IsEnabled) +{ + int Status = XST_SUCCESS; + + /* Verify arguments */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check HDMI receive */ + if (XHdcp1x_CipherIsHDMI(InstancePtr)) { + + u32 Val = 0; + + /* Clear any pending link state failure interrupt */ + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_STATUS, + XHDCP1X_CIPHER_BITMASK_INTERRUPT_Ri_UPDATE); + + /* Update theDevice */ + Val = RegRead(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_MASK); + if (IsEnabled) { + Val &= ~XHDCP1X_CIPHER_BITMASK_INTERRUPT_Ri_UPDATE; + } + else { + Val |= XHDCP1X_CIPHER_BITMASK_INTERRUPT_Ri_UPDATE; + } + RegWrite(InstancePtr, XHDCP1X_CIPHER_REG_INTERRUPT_MASK, Val); + } + else { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function is the interrupt handler for the cipher core driver +* +* @param InstancePtr the cipher core instance +* +* @return +* void +* +* @note +* none +* +******************************************************************************/ +void XHdcp1x_CipherHandleInterrupt(void *InstancePtr) +{ + XHdcp1x_Cipher *HdcpCipherPtr = (XHdcp1x_Cipher *) InstancePtr; + u32 Pending = 0; + + /* Verify arguments */ + Xil_AssertVoid(HdcpCipherPtr != NULL); + Xil_AssertVoid(HdcpCipherPtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Determine Pending */ + Pending = RegRead(HdcpCipherPtr, XHDCP1X_CIPHER_REG_INTERRUPT_STATUS); + Pending &= ~RegRead(HdcpCipherPtr, XHDCP1X_CIPHER_REG_INTERRUPT_MASK); + + /* Check for pending */ + if (Pending != 0) { + + /* Clear Pending */ + RegWrite(HdcpCipherPtr, XHDCP1X_CIPHER_REG_INTERRUPT_STATUS, + Pending); + + /* Update statistics */ + HdcpCipherPtr->Stats.IntCount++; + + /* Check for link integrity failure */ + if (Pending & XHDCP1X_CIPHER_BITMASK_INTERRUPT_LINK_FAIL) { + + /* Invoke callback if set */ + if (HdcpCipherPtr->IsLinkFailCallbackSet) + (*HdcpCipherPtr->LinkFailCallback)( + HdcpCipherPtr->LinkFailRef); + } + + /* Check for change to Ri register */ + if (Pending & XHDCP1X_CIPHER_BITMASK_INTERRUPT_Ri_UPDATE) { + + /* Invoke callback if set */ + if (HdcpCipherPtr->IsRiUpdateCallbackSet) + (*HdcpCipherPtr->RiUpdateCallback)( + HdcpCipherPtr->RiUpdateRef); + } + } + + return; +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_selftest.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_selftest.c new file mode 100644 index 00000000..87886b39 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_cipher_selftest.c @@ -0,0 +1,125 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_selftest.c +* +* This file contains self test function for the Xilinx HDCP Cipher core. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xhdcp1x_cipher.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/**************************** Type Definitions *******************************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Definitions *****************************/ + + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function self tests an hdcp cipher core +* +* @param InstancePtr the cipher core to test +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_CipherSelfTest(XHdcp1x_Cipher *InstancePtr) +{ + u32 Base = 0; + u32 Value = 0; + int Status = XST_FAILURE; + + /* Verify parameters */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Base */ + Base = InstancePtr->CfgPtr->BaseAddress; + + /* Read the version */ + Value = XHdcp1x_CipherReadReg(Base, XHDCP1X_CIPHER_REG_VERSION); + + /* Confirm the version is reasonable */ + if ((Value != 0u) && (Value != ((u32) (-1)))) { + + const XHdcp1x_Config *CfgPtr = InstancePtr->CfgPtr; + int IsRx = FALSE; + int IsHdmi = FALSE; + + /* Determine isRx */ + Value = XHdcp1x_CipherReadReg(Base, XHDCP1X_CIPHER_REG_TYPE); + Value &= XHDCP1X_CIPHER_BITMASK_TYPE_DIRECTION; + if (Value == XHDCP1X_CIPHER_VALUE_TYPE_DIRECTION_RX) + IsRx = TRUE; + + /* Determine isHdmi */ + Value = XHdcp1x_CipherReadReg(Base, XHDCP1X_CIPHER_REG_TYPE); + Value &= XHDCP1X_CIPHER_BITMASK_TYPE_PROTOCOL; + if (Value == XHDCP1X_CIPHER_VALUE_TYPE_PROTOCOL_HDMI) + IsHdmi = TRUE; + + /* Confirm direction and protocol match */ + if (((IsRx == CfgPtr->IsRx)) && ((IsHdmi == CfgPtr->IsHDMI))) + Status = XST_SUCCESS; + } + + return (Status); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_debug.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_debug.h new file mode 100644 index 00000000..1a2ee525 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_debug.h @@ -0,0 +1,78 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_debug.h +* +* This file provides the interface of the HDCP debug commands +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ +#ifndef XHDCP1X_DEBUG_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_DEBUG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ +#define XHDCP1X_DEBUG_PRINTF if (XHdcp1xDebugPrintf != NULL) XHdcp1xDebugPrintf +#define XHDCP1X_DEBUG_LOGMSG if (XHdcp1xDebugLogMsg != NULL) XHdcp1xDebugLogMsg + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +/************************* External Declarations******************************/ +extern XHdcp1x_Printf XHdcp1xDebugPrintf; +extern XHdcp1x_LogMsg XHdcp1xDebugLogMsg; + +#ifdef __cplusplus +} +#endif + + +#endif /* XHDCP1X_DEBUG_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_intr.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_intr.c new file mode 100644 index 00000000..6038e20e --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_intr.c @@ -0,0 +1,116 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_cipher_intr.c +* +* This file contains interrupt related functions for Xilinx HDCP core. +* Please see xhdcp_cipher.h for more details of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xhdcp1x_cipher.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function is the cipher interrupt handler for the HDCP module +* +* @param InstancePtr the device instance that just interrupted +* +* @return +* void +* +* @note +* This function just forwards the interrupt along to the corresponding +* cipher core. +* +******************************************************************************/ +void XHdcp1x_CipherIntrHandler(void *InstancePtr) +{ + XHdcp1x* HdcpPtr = InstancePtr; + + /* Verify arguments */ + Xil_AssertVoid(HdcpPtr != NULL); + Xil_AssertVoid(HdcpPtr->Common.IsReady == XIL_COMPONENT_IS_READY); + + /* Dispatch it to the corresponding cipher */ + XHdcp1x_CipherHandleInterrupt(&(HdcpPtr->Common.Cipher)); +} + +/*****************************************************************************/ +/** +* +* This function is the port interrupt handler for the HDCP module +* +* @param InstancePtr the device instance that just interrupted +* @param IntCause the interrupt cause bit map +* +* @return +* void +* +* @note +* This function just forwards the interrupt along to the corresponding +* cipher core. +* +******************************************************************************/ +void XHdcp1x_PortIntrHandler(void *InstancePtr, u32 IntCause) +{ + XHdcp1x* HdcpPtr = InstancePtr; + + /* Verify arguments */ + Xil_AssertVoid(HdcpPtr != NULL); + Xil_AssertVoid(HdcpPtr->Common.IsReady == XIL_COMPONENT_IS_READY); + + /* Dispatch it to the corresponding port */ + XHdcp1x_PortHandleInterrupt(&(HdcpPtr->Common.Port), IntCause); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_platform.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_platform.c new file mode 100644 index 00000000..478b7364 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_platform.c @@ -0,0 +1,188 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_platform.c +* +* This file provides the implementation for the hdcp platform integration +* module +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xhdcp1x_platform.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Extern Declarations ******************************/ +extern XHdcp1x_KsvRevokeCheck XHdcp1xKsvRevokeCheck; +extern XHdcp1x_TimerStart XHdcp1xTimerStart; +extern XHdcp1x_TimerStop XHdcp1xTimerStop; +extern XHdcp1x_TimerDelay XHdcp1xTimerDelay; + +/************************** Function Prototypes ******************************/ + +/*****************************************************************************/ +/** +* +* This function checks a KSV value to determine if it has been revoked or not +* +* @param InstancePtr the hdcp interface +* @param Ksv the KSV to check +* +* @return +* Truth value indicating the KSV is revoked (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PlatformIsKsvRevoked(const XHdcp1x *InstancePtr, u64 Ksv) +{ + int IsRevoked = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Sanity Check */ + if (XHdcp1xKsvRevokeCheck != NULL) { + IsRevoked = (*XHdcp1xKsvRevokeCheck)(InstancePtr, Ksv); + } + + return (IsRevoked); +} + +/*****************************************************************************/ +/** +* +* This function starts a timer on behalf of an hdcp interface +* +* @param InstancePtr the hdcp interface +* @param TimeoutInMs the duration of the timer in milliseconds +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PlatformTimerStart(XHdcp1x *InstancePtr, u16 TimeoutInMs) +{ + int Status = XST_SUCCESS; + + /* Sanity Check */ + if (XHdcp1xTimerStart != NULL) { + Status = (*XHdcp1xTimerStart)(InstancePtr, TimeoutInMs); + } + else { + Status = XST_FAILURE; + } + + return (Status); +} + + +/*****************************************************************************/ +/** +* +* This function stop a timer on behalf of an hdcp interface +* +* @param InstancePtr the hdcp interface +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PlatformTimerStop(XHdcp1x *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Sanity Check */ + if (XHdcp1xTimerStop != NULL) { + Status = (*XHdcp1xTimerStop)(InstancePtr); + } + else { + Status = XST_FAILURE; + } + + return (Status); +} + + +/*****************************************************************************/ +/** +* +* This function busy waits on a timer for a number of milliseconds +* +* @param InstancePtr the hdcp interface +* @param DelayInMs the delay time in milliseconds +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PlatformTimerBusy(XHdcp1x *InstancePtr, u16 DelayInMs) +{ + int Status = XST_SUCCESS; + + /* Sanity Check */ + if (XHdcp1xTimerDelay != NULL) { + Status = (*XHdcp1xTimerDelay)(InstancePtr, DelayInMs); + } + else { + Status = XST_FAILURE; + } + + return (Status); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_platform.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_platform.h new file mode 100644 index 00000000..ee848c68 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_platform.h @@ -0,0 +1,78 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_platform.h +* +* This file provides the interface for the hdcp platform integration module +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ +#ifndef XHDCP1X_PLATFORM_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_PLATFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ +int XHdcp1x_PlatformIsKsvRevoked(const XHdcp1x *InstancePtr, u64 Ksv); + +int XHdcp1x_PlatformTimerStart(XHdcp1x *InstancePtr, u16 TimeoutInMs); +int XHdcp1x_PlatformTimerStop(XHdcp1x *InstancePtr); +int XHdcp1x_PlatformTimerBusy(XHdcp1x *InstancePtr, u16 DelayInMs); + +#ifdef __cplusplus +} +#endif + + +#endif /* XHDCP1X_PLATFORM_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port.c new file mode 100644 index 00000000..271d5bcd --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port.c @@ -0,0 +1,453 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +*****************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port.c +* +* This contains the main implementation file for the Xilinx HDCP Port driver +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +*****************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "xhdcp1x_port.h" +#include "xil_assert.h" +#include "xil_types.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ +#if defined(XPAR_XHDMI_TX_NUM_INSTANCES) && (XPAR_XHDMI_TX_NUM_INSTANCES > 0) +#define INCLUDE_HDMI_TX +#endif +#if defined(XPAR_XHDMI_RX_NUM_INSTANCES) && (XPAR_XHDMI_RX_NUM_INSTANCES > 0) +#define INCLUDE_HDMI_RX +#endif +#if defined(XPAR_XDP_NUM_INSTANCES) && (XPAR_XDP_NUM_INSTANCES > 0) +#define INCLUDE_DP_TX +#define INCLUDE_DP_RX +#endif + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Extern Declarations ******************************/ + +#if defined(INCLUDE_HDMI_TX) +extern const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortHdmiTxAdaptor; +#endif +#if defined(INCLUDE_HDMI_RX) +extern const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortHdmiRxAdaptor; +#endif +#if defined(INCLUDE_DP_TX) +extern const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortDpTxAdaptor; +#endif +#if defined(INCLUDE_DP_RX) +extern const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortDpRxAdaptor; +#endif + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function determines the adaptor for a specified port device +* +* @param InstancePtr the device whose adaptor is to be determined +* +* @return +* Pointer to the adaptor table. NULL if not found. +* +* @note +* None. +* +******************************************************************************/ +static const XHdcp1x_PortPhyIfAdaptor *DetermineAdaptor( + const XHdcp1x_Port *InstancePtr) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + const XHdcp1x_Config *CfgPtr = InstancePtr->CfgPtr; + +#if defined(INCLUDE_HDMI_RX) + /* Check for HDMI Rx */ + if ((CfgPtr->IsRx) && (CfgPtr->IsHDMI)) { + Adaptor = &XHdcp1x_PortHdmiRxAdaptor; + } + else +#endif +#if defined(INCLUDE_HDMI_TX) + /* Check for HDMI Tx */ + if (!(CfgPtr->IsRx) && (CfgPtr->IsHDMI)) { + Adaptor = &XHdcp1x_PortHdmiTxAdaptor; + } + else +#endif +#if defined(INCLUDE_DP_RX) + /* Check for DP Rx */ + if ((CfgPtr->IsRx) && !(CfgPtr->IsHDMI)) { + Adaptor = &XHdcp1x_PortDpRxAdaptor; + } + else +#endif +#if defined(INCLUDE_DP_TX) + /* Check for DP Tx */ + if (!(CfgPtr->IsRx) && !(CfgPtr->IsHDMI)) { + Adaptor = &XHdcp1x_PortDpTxAdaptor; + } + else +#endif + { + Adaptor = NULL; + } + + return (Adaptor); +} + +/*****************************************************************************/ +/** +* +* This function initializes a port device +* +* @param InstancePtr the device to initialize +* @param CfgPtr the hdcp configuration structure +* @param PhyIfPtr pointer to the underlying physical interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortCfgInitialize(XHdcp1x_Port *InstancePtr, + const XHdcp1x_Config *CfgPtr, void* PhyIfPtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + Xil_AssertNonvoid(PhyIfPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady != XIL_COMPONENT_IS_READY); + + /* Initialize InstancePtr */ + memset(InstancePtr, 0, sizeof(XHdcp1x_Port)); + InstancePtr->CfgPtr = CfgPtr; + InstancePtr->PhyIfPtr = PhyIfPtr; + InstancePtr->Adaptor = DetermineAdaptor(InstancePtr); + + /* Sanity Check */ + if (InstancePtr->Adaptor == NULL) { + Status = XST_NO_FEATURE; + } + /* Invoke adaptor function if present */ + else if (InstancePtr->Adaptor->Init != NULL) { + Status = (*(InstancePtr->Adaptor->Init))(InstancePtr); + } + + /* Set IsReady */ + if (Status == XST_SUCCESS) { + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function enables a port device +* +* @param InstancePtr the device to enables +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortEnable(XHdcp1x_Port *InstancePtr) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Sanity Check */ + if (Adaptor == NULL) { + Status = XST_NO_FEATURE; + } + /* Invoke adaptor function if present */ + else if (Adaptor->Enable != NULL) { + Status = (*(Adaptor->Enable))(InstancePtr); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables a port device +* +* @param InstancePtr the device to disables +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDisable(XHdcp1x_Port *InstancePtr) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Sanity Check */ + if (Adaptor == NULL) { + Status = XST_NO_FEATURE; + } + /* Invoke adaptor function if present */ + else if (Adaptor->Disable != NULL) { + Status = (*(Adaptor->Disable))(InstancePtr); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function queries a port device to determine if hdcp is supported +* +* @param InstancePtr the device to query +* +* @return +* Truth value +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortIsCapable(const XHdcp1x_Port *InstancePtr) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + int IsCapable = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Invoke adaptor function if present */ + if ((Adaptor != NULL) && (Adaptor->IsCapable != NULL)) { + IsCapable = (*(Adaptor->IsCapable))(InstancePtr); + } + + return (IsCapable); +} + +/*****************************************************************************/ +/** +* +* This function queries a port device to determine if it is connected to a +* repeater. +* +* @param InstancePtr the device to query +* +* @return +* Truth value +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortIsRepeater(const XHdcp1x_Port *InstancePtr) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + int IsRepeater = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Invoke adaptor function if present */ + if ((Adaptor != NULL) && (Adaptor->IsRepeater != NULL)) { + IsRepeater = (*(Adaptor->IsRepeater))(InstancePtr); + } + + return (IsRepeater); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the repeater information from the connected device +* +* @param InstancePtr the device to query +* @param InfoPtr the repeater info +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortGetRepeaterInfo(XHdcp1x_Port *InstancePtr, u16 *InfoPtr) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InfoPtr != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Sanity Check */ + if (Adaptor == NULL) { + Status = XST_NO_FEATURE; + } + /* Invoke adaptor function if present */ + else if (Adaptor->GetRepeaterInfo != NULL) { + Status = (*(Adaptor->GetRepeaterInfo))(InstancePtr, InfoPtr); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function reads a register from a hdcp port device +* +* @param InstancePtr the device to read from +* @param Offset the offset to start reading from +* @param Buf the buffer to copy the data read +* @param BufSize the size of the buffer +* +* @return +* The number of bytes read +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortRead(const XHdcp1x_Port *InstancePtr, u8 Offset, void *Buf, + u32 BufSize) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + int NumRead = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Invoke adaptor function if present */ + if ((Adaptor != NULL) && (Adaptor->Read != NULL)) { + NumRead = (*(Adaptor->Read))(InstancePtr, Offset, Buf, + BufSize); + } + + /* Return */ + return (NumRead); +} + +/*****************************************************************************/ +/** +* +* This function writes a register within a hdcp port device +* +* @param InstancePtr the device to write to +* @param Offset the offset to start writing at +* @param Buf the buffer containing the data to write +* @param BufSize the size of the buffer +* +* @return +* The number of bytes written +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortWrite(XHdcp1x_Port *InstancePtr, u8 Offset, const void *Buf, + u32 BufSize) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + int NumWritten = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Invoke adaptor function if present */ + if ((Adaptor != NULL) && (Adaptor->Write != NULL)) { + NumWritten = (*(Adaptor->Write))(InstancePtr, Offset, Buf, + BufSize); + } + + return (NumWritten); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port.h new file mode 100644 index 00000000..bac583e0 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port.h @@ -0,0 +1,226 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port.h +* +* This header file contains the external declarations associated with the +* HDCP port driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ +#ifndef XHDCP1X_PORT_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_PORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xparameters.h" +#include "xstatus.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/** + * This typedef defines the different types of handlers that can be registered + * to service interrupt requests from the HDCP port instance + */ +typedef enum { + XHDCP1X_PORT_HANDLER_AUTHENTICATE = 1, /**< An (re)auth request */ +} XHdcp1x_PortHandlerType; + +/** + * The typedef defines the HDCP port adaptor table. This contains a series of + * functions that map the external interface of the HDCP port device to the + * underlying physical interface that it is running over + */ +typedef struct XHdcp1x_PortPhyIfAdaptorS { + int (*Init)(XHdcp1x_Port*); /**< Initialization function */ + int (*Enable)(XHdcp1x_Port*); /**< Enable function */ + int (*Disable)(XHdcp1x_Port*); /**< Disable function */ + int (*Read)(const XHdcp1x_Port*, u8, void*, u32); /**< Reg read */ + int (*Write)(XHdcp1x_Port*, u8, const void*, u32); /**< Reg write */ + int (*IsCapable)(const XHdcp1x_Port*); /**< Tests for HDCP capable */ + int (*IsRepeater)(const XHdcp1x_Port*); /**< Tests for repeater */ + int (*GetRepeaterInfo)(const XHdcp1x_Port*, u16*); /**< Gets repeater info */ + void (*IntrHandler)(XHdcp1x_Port *, u32); /**< Interrupt handler */ +} XHdcp1x_PortPhyIfAdaptor; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This macro converts from an unsigned integer to a little endian formatted +* buffer +* +* @param buf the buffer to write to +* @param uint the unsigned integer to convert +* @param numbits the number of bits within the unsigned integer to use +* +* @return +* void +* +* @note +* The value of the "uint" parameter is destroyed by a call to this macro +* +******************************************************************************/ +#define XHDCP1X_PORT_UINT_TO_BUF(buf, uint, numbits) \ + if ((numbits) > 0) { \ + int byte; \ + for (byte=0; byte<=(((numbits)-1)>>3); byte++) { \ + buf[byte] = (uint8_t) (uint & 0xFFu); \ + uint >>= 8; \ + } \ + } + +/*****************************************************************************/ +/** +* +* This macro converts from a little endian formatted buffer to an unsigned +* integer value +* +* @param uint the unsigned integer to write +* @param buf the buffer to convert +* @param numbits the number of bits within the buffer to use +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +#define XHDCP1X_PORT_BUF_TO_UINT(uint, buf, numbits) \ + if ((numbits) > 0) { \ + int byte; \ + uint = 0; \ + for (byte=(((numbits)-1)>>3); byte>=0; byte--) { \ + uint <<= 8; \ + uint |= buf[byte]; \ + } \ + } + +/*****************************************************************************/ +/** +* +* This macro sets a bit within a little endian formatted buffer +* +* @param buf the buffer to write to +* @param bitnum the bit to set +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +#define XHDCP1X_PORT_BSET_IN_BUF(buf, bitnum) \ + buf[(bitnum)>>3] |= (1u << ((bitnum) & 0x07u)); + +/*****************************************************************************/ +/** +* +* This macro clears a bit within a little endian formatted buffer +* +* @param buf the buffer to write to +* @param bitnum the bit to clear +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +#define XHDCP1X_PORT_BCLR_IN_BUF(buf, bitnum) \ + buf[(bitnum)>>3] &= ~(1u << ((bitnum) & 0x07u)); + +/*****************************************************************************/ +/** +* +* This macro tests a bit within a little endian formatted buffer +* +* @param buf the buffer containing the bit to test +* @param bitnum the bit to test +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +#define XHDCP1X_PORT_BTST_IN_BUF(buf, bitnum) \ + (buf[(bitnum)>>3] & (1u << ((bitnum) & 0x07u))) + +/************************** Function Prototypes ******************************/ + +int XHdcp1x_PortCfgInitialize(XHdcp1x_Port *InstancePtr, + const XHdcp1x_Config* ConfigPtr, void *PhyIfPtr); + +int XHdcp1x_PortSetCallback(XHdcp1x_Port* InstancePtr, u32 HandlerType, + XHdcp1x_Callback Callback, void *Parameter); + +int XHdcp1x_PortEnable(XHdcp1x_Port *InstancePtr); +int XHdcp1x_PortDisable(XHdcp1x_Port *InstancePtr); +int XHdcp1x_PortIsCapable(const XHdcp1x_Port *InstancePtr); +int XHdcp1x_PortIsRepeater(const XHdcp1x_Port *InstancePtr); +int XHdcp1x_PortGetRepeaterInfo(XHdcp1x_Port *InstancePtr, u16 *Info); +int XHdcp1x_PortRead(const XHdcp1x_Port *InstancePtr, u8 Offset, void *Buf, + u32 BufSize); +int XHdcp1x_PortWrite(XHdcp1x_Port *InstancePtr, u8 Offset, const void *Buf, + u32 BufSize); + +void XHdcp1x_PortHandleInterrupt(XHdcp1x_Port *InstancePtr, u32 IntCause); + +#ifdef __cplusplus +} +#endif + +#endif /* XHDCP1X_PORT_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp.h new file mode 100644 index 00000000..14a6d03b --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp.h @@ -0,0 +1,136 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port_dp.h +* +* This file contains the definitions for the hdcp port registers/offsets for +* display port interfaces +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +#ifndef XHDCP1X_PORT_DP_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_PORT_DP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#if defined(XHDCP1X_PORT_HDMI_H) +#error "cannot include both xhdcp1x_port_dp.h and xhdcp1x_port_hdmi.h" +#endif + +/************************** Constant Definitions *****************************/ + +/** + * These constants specify the offsets for the various fields and/or + * attributes within the hdcp port + */ +#define XHDCP1X_PORT_OFFSET_BKSV (0x00u) /**< Bksv Offset */ +#define XHDCP1X_PORT_OFFSET_RO (0x05u) /**< R0' Offset */ +#define XHDCP1X_PORT_OFFSET_AKSV (0x07u) /**< Aksv Offset */ +#define XHDCP1X_PORT_OFFSET_AN (0x0Cu) /**< An Offset */ +#define XHDCP1X_PORT_OFFSET_VH0 (0x14u) /**< V'.H0 Offset */ +#define XHDCP1X_PORT_OFFSET_VH1 (0x18u) /**< V'.H1 Offset */ +#define XHDCP1X_PORT_OFFSET_VH2 (0x1Cu) /**< V'.H2 Offset */ +#define XHDCP1X_PORT_OFFSET_VH3 (0x20u) /**< V'.H3 Offset */ +#define XHDCP1X_PORT_OFFSET_VH4 (0x24u) /**< V'.H4 Offset */ +#define XHDCP1X_PORT_OFFSET_BCAPS (0x28u) /**< Bcaps Offset */ +#define XHDCP1X_PORT_OFFSET_BSTATUS (0x29u) /**< Bstatus Offset */ +#define XHDCP1X_PORT_OFFSET_BINFO (0x2Au) /**< Binfo Offset */ +#define XHDCP1X_PORT_OFFSET_KSVFIFO (0x2Cu) /**< KSV FIFO Offset */ +#define XHDCP1X_PORT_OFFSET_AINFO (0x3Bu) /**< Ainfo Offset */ +#define XHDCP1X_PORT_OFFSET_DBG (0xC0u) /**< Debug Space Offset */ + +/** + * These constants specify the sizes for the various fields and/or + * attributes within the hdcp port + */ +#define XHDCP1X_PORT_SIZE_BKSV (0x05u) /**< Bksv Size */ +#define XHDCP1X_PORT_SIZE_RO (0x02u) /**< R0' Size */ +#define XHDCP1X_PORT_SIZE_AKSV (0x05u) /**< Aksv Size */ +#define XHDCP1X_PORT_SIZE_AN (0x08u) /**< An Size */ +#define XHDCP1X_PORT_SIZE_VH0 (0x04u) /**< V'.H0 Size */ +#define XHDCP1X_PORT_SIZE_VH1 (0x04u) /**< V'.H1 Size */ +#define XHDCP1X_PORT_SIZE_VH2 (0x04u) /**< V'.H2 Size */ +#define XHDCP1X_PORT_SIZE_VH3 (0x04u) /**< V'.H3 Size */ +#define XHDCP1X_PORT_SIZE_VH4 (0x04u) /**< V'.H4 Size */ +#define XHDCP1X_PORT_SIZE_BCAPS (0x01u) /**< Bcaps Size */ +#define XHDCP1X_PORT_SIZE_BSTATUS (0x01u) /**< Bstatus Size */ +#define XHDCP1X_PORT_SIZE_BINFO (0x02u) /**< Binfo Size */ +#define XHDCP1X_PORT_SIZE_KSVFIFO (0x0Fu) /**< KSV FIFO Size */ +#define XHDCP1X_PORT_SIZE_AINFO (0x01u) /**< Ainfo Offset */ +#define XHDCP1X_PORT_SIZE_DBG (0x40u) /**< Debug Space Size */ + +/** + * These constants specify the bit definitions within the various fields + * and/or attributes within the hdcp port + */ +#define XHDCP1X_PORT_BIT_BSTATUS_READY (1u << 0) +#define XHDCP1X_PORT_BIT_BSTATUS_RO_AVAILABLE (1u << 1) +#define XHDCP1X_PORT_BIT_BSTATUS_LINK_FAILURE (1u << 2) +#define XHDCP1X_PORT_BIT_BSTATUS_REAUTH_REQUEST (1u << 3) + +#define XHDCP1X_PORT_BIT_BCAPS_HDCP_CAPABLE (1u << 0) +#define XHDCP1X_PORT_BIT_BCAPS_REPEATER (1u << 1) + +#define XHDCP1X_PORT_BIT_AINFO_REAUTH_ENABLE_IRQ (1u << 0) + +/** + * This constant defines the base address of the hdcp port within the DPCD + * address space + */ +#define XHDCP1X_PORT_DPCD_BASE (0x68000u) /**< Base Addr in DPCD */ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XHDCP1X_PORT_DP_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp_rx.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp_rx.c new file mode 100644 index 00000000..31b40fbe --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp_rx.c @@ -0,0 +1,655 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port_dp_rx.c +* +* This contains the implementation of the HDCP port driver for Xilinx DP +* RX interfaces +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" + +#if defined(XPAR_XDP_NUM_INSTANCES) && (XPAR_XDP_NUM_INSTANCES > 0) +#include +#include +#include "xhdcp1x_port.h" +#include "xhdcp1x_port_dp.h" +#include "xdp.h" +#include "xdp_hw.h" +#include "xil_assert.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This reads a register from the hdcp port device +* +* @param InstancePtr device to read from +* @param Offset offset to start reading from +* @param Buf buffer to copy data read +* @param BufSize size of buffer +* +* @return +* number of bytes read +* +* @note +* None. +* +******************************************************************************/ +static int RegRead(const XHdcp1x_Port *InstancePtr, u8 Offset, u8 *Buf, + u32 BufSize) +{ + XDprx* HwDp = InstancePtr->PhyIfPtr; + u32 Base = HwDp->Config.BaseAddr; + u32 RegOffset = 0; + int NumRead = 0; + + /* Determine RegOffset */ + RegOffset = XDP_RX_DPCD_HDCP_TABLE; + RegOffset += Offset; + + /* Iterate through the reads */ + do { + u32 Value = 0; + u32 Alignment = 0; + u32 NumThisTime = 0; + int Idx = 0; + + /* Determine Alignment */ + Alignment = (RegOffset & 0x03ul); + + /* Determine NumThisTime */ + NumThisTime = 4; + if (Alignment != 0) { + NumThisTime = (4 - Alignment); + } + if (NumThisTime > BufSize) { + NumThisTime = BufSize; + } + + /* Determine Value */ + Value = XDprx_ReadReg(Base, (RegOffset & ~0x03ul)); + + /* Check for adjustment of Value */ + if (Alignment != 0) + Value >>= (8*Alignment); + + /* Update theBuf */ + for (Idx=0; Idx>= 8; + } + + /* Update for loop */ + Buf += NumThisTime; + BufSize -= NumThisTime; + RegOffset += NumThisTime; + NumRead += NumThisTime; + } + while (BufSize > 0); + + return (NumRead); +} + +/*****************************************************************************/ +/** +* +* This writes a register from the hdcp port device +* +* @param InstancePtr device to write to +* @param Offset offset to start writing at +* @param Buf buffer containing data to write +* @param BufSize size of buffer +* +* @return +* number of bytes written +* +* @note +* None. +* +******************************************************************************/ +static int RegWrite(XHdcp1x_Port *InstancePtr, u8 Offset, const u8 *Buf, + u32 BufSize) +{ + XDprx* HwDp = InstancePtr->PhyIfPtr; + u32 Base = HwDp->Config.BaseAddr; + u32 RegOffset = 0; + int NumWritten = 0; + + /* Determine RegOffset */ + RegOffset = XDP_RX_DPCD_HDCP_TABLE; + RegOffset += Offset; + + /* Iterate through the writes */ + do { + u32 Value = 0; + u32 Alignment = 0; + u32 NumThisTime = 0; + int Idx = 0; + + /* Determine Alignment */ + Alignment = (RegOffset & 0x03ul); + + /* Determine NumThisTime */ + NumThisTime = 4; + if (Alignment != 0) { + NumThisTime = (4 - Alignment); + } + if (NumThisTime > BufSize) { + NumThisTime = BufSize; + } + + /* Check for simple case */ + if (NumThisTime == 4) { + /* Determine Value */ + for (Idx=3; Idx>=0; Idx--) { + Value <<= 8; + Value |= Buf[Idx]; + } + } + /* Otherwise - must read and modify existing memory */ + else { + u32 Mask = 0; + u32 Temp = 0; + + /* Determine Mask */ + Mask = 0xFFu; + if (Alignment != 0) { + Mask <<= (8*Alignment); + } + + /* Initialize Value */ + Value = XDprx_ReadReg(Base, (RegOffset & ~0x03ul)); + + /* Update theValue */ + for (Idx=0; Idx 0); + + return (NumWritten); +} + +/*****************************************************************************/ +/** +* +* This function notifies the tx end of the link of an event of interest +* +* @param InstancePtr device to perform the notification +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void NotifyTx(const XHdcp1x_Port *InstancePtr) +{ + XDprx* HwDp = InstancePtr->PhyIfPtr; + u32 Base = HwDp->Config.BaseAddr; + u32 Value = 0; + u8 Ainfo = 0; + + /* Read Ainfo */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_AINFO, &Ainfo, sizeof(Ainfo)); + + /* Check for regular HPD pulse notification */ + if ((Ainfo & 0x01u) == 0) { + /* Send a 500us HPD pulse */ + XDp_RxGenerateHpdInterrupt(HwDp, 500u); + } + /* Otherwise - must use HPD IRQ */ + else { + /* #### WORK TO DO #### */ + } + + /* Always generate CP IRQ */ + Value = XDprx_ReadReg(Base, XDP_RX_DEVICE_SERVICE_IRQ); + Value |= XDP_RX_DEVICE_SERVICE_IRQ_CP_IRQ_MASK; + XDprx_WriteReg(Base, XDP_RX_DEVICE_SERVICE_IRQ, Value); + + return; +} + +/*****************************************************************************/ +/** +* +* This function process a write to the AKsv register from the tx device +* +* @param CallbackRef device to whose register was written +* +* @return +* void +* +* @note +* This function initiates the side effects of the tx device writing the +* Aksv register. This is currently updates some status bits as well as +* kick starts a re-authentication process. +* +******************************************************************************/ +static void ProcessAKsvWrite(void *CallbackRef) +{ + XHdcp1x_Port *InstancePtr = CallbackRef; + u8 Value = 0; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Update statistics */ + InstancePtr->Stats.IntCount++; + + /* Clear bit 0 of Ainfo register */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_AINFO, &Value, 1); + Value &= 0xFEu; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_AINFO, &Value, 1); + + /* Clear bits 3:2 of Bstatus register */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Value, 1); + Value &= 0xF3u; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Value, 1); + + /* Invoke authentication callback if set */ + if (InstancePtr->IsAuthCallbackSet) { + (*(InstancePtr->AuthCallback))(InstancePtr->AuthRef); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function process a read of the Ro' register by the tx device +* +* @param CallbackRef device to whose register was read +* +* @return +* void +* +* @note +* This function initiates the side effects of the tx device read the Ro' +* register. This is currently limited to the clearing of bits within +* device's Bstatus register. +* +******************************************************************************/ +static void ProcessRoRead(void *CallbackRef) +{ + XHdcp1x_Port *InstancePtr = CallbackRef; + u8 Value = 0; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Update statistics */ + InstancePtr->Stats.IntCount++; + + /* Clear bit 1 of Bstatus register */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Value, 1); + Value &= 0xFDu; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Value, 1); + + return; +} + +/*****************************************************************************/ +/** +* +* This function process a read of the Binfo register by the tx device +* +* @param CallbackRef device to whose register was read +* +* @return +* void +* +* @note +* This function initiates the side effects of the tx device read the Binfo +* register. This is currently limited to the clearing of bits within +* device's Bstatus register. +* +******************************************************************************/ +static void ProcessBinfoRead(void *CallbackRef) +{ + XHdcp1x_Port *InstancePtr = CallbackRef; + u8 Value = 0; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Update statistics */ + InstancePtr->Stats.IntCount++; + + /* Clear bit 0 of Bstatus register */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Value, 1); + Value &= 0xFEu; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Value, 1); + + return; +} + +/*****************************************************************************/ +/** +* +* This function enables a hdcp port device +* +* @param InstancePtr device to enable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpRxEnable(XHdcp1x_Port *InstancePtr) +{ + XDprx* HwDp = InstancePtr->PhyIfPtr; + u32 IntMask = 0; + u8 Buf[4]; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Initialize Buf */ + memset(Buf, 0, 4); + + /* Initialize Bstatus register */ + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, 1); + + /* Initialize Binfo register */ + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BINFO, Buf, 2); + + /* Initialize Bcaps register */ + Buf[0] |= XHDCP1X_PORT_BIT_BCAPS_HDCP_CAPABLE; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, Buf, 1); + + /* Initialize some debug registers */ + Buf[0] = 0xDE; + Buf[1] = 0xAD; + Buf[2] = 0xBE; + Buf[3] = 0xEF; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_DBG, Buf, 4); + + /* Register callbacks */ + XDp_RxSetIntrHdcpAksvWriteHandler(HwDp, &ProcessAKsvWrite, + InstancePtr); + XDp_RxSetIntrHdcpBinfoReadHandler(HwDp, &ProcessBinfoRead, + InstancePtr); + XDp_RxSetIntrHdcpRoReadHandler(HwDp, &ProcessRoRead, + InstancePtr); + + /* Enable interrupts */ + IntMask = XDP_RX_INTERRUPT_MASK_HDCP_AKSV_WRITE_MASK; + IntMask |= XDP_RX_INTERRUPT_MASK_HDCP_RO_READ_MASK; + IntMask |= XDP_RX_INTERRUPT_MASK_HDCP_BINFO_READ_MASK; + XDp_RxInterruptEnable(HwDp, IntMask); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables a hdcp port device +* +* @param InstancePtr device to disable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpRxDisable(XHdcp1x_Port *InstancePtr) +{ + XDprx* HwDp = InstancePtr->PhyIfPtr; + u32 IntMask = 0; + u8 Offset = 0; + u8 Value = 0; + int NumLeft = 0; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Disable interrupts */ + IntMask = XDP_RX_INTERRUPT_MASK_HDCP_AKSV_WRITE_MASK; + IntMask |= XDP_RX_INTERRUPT_MASK_HDCP_RO_READ_MASK; + IntMask |= XDP_RX_INTERRUPT_MASK_HDCP_BINFO_READ_MASK; + XDp_RxInterruptDisable(HwDp, IntMask); + + /* Clear hdcp registers */ + Value = 0; + Offset = 0; + NumLeft = 256; + while (NumLeft-- > 0) { + RegWrite(InstancePtr, Offset++, &Value, sizeof(Value)); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function initializes a hdcp port device +* +* @param InstancePtr device to initialize +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpRxInit(XHdcp1x_Port *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Disable it */ + if (XHdcp1x_PortDpRxDisable(InstancePtr) != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function reads a register from a hdcp port device +* +* @param InstancePtr device to read from +* @param Offset offset to start reading from +* @param Buf buffer to copy data read +* @param BufSize size of buffer +* +* @return +* number of bytes read +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpRxRead(const XHdcp1x_Port *InstancePtr, u8 Offset, + void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Read it */ + return (RegRead(InstancePtr, Offset, Buf, BufSize)); +} + +/*****************************************************************************/ +/** +* +* This function writes a register from a hdcp port device +* +* @param InstancePtr device to write to +* @param Offset offset to start writing to +* @param Buf buffer containing data to write +* @param BufSize size of buffer +* +* @return +* number of bytes written +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpRxWrite(XHdcp1x_Port *InstancePtr, u8 Offset, + const void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Write it */ + return (RegWrite(InstancePtr, Offset, Buf, BufSize)); +} + +#if 0 +/*****************************************************************************/ +/** +* +* This handles an interrupt generated by a hdcp port device +* +* @param InstancePtr the device to write to +* @param IntCause the interrupt cause bit map +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_PortDpRxIntrHandler(XHdcp1x_Port *InstancePtr, u32 IntCause) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Check for AKsv write */ + if (IntCause & XDP_RX_INTERRUPT_MASK_HDCP_AKSV_WRITE_MASK) { + ProcessAKsvWrite(InstancePtr); + } + /* Check for Ro read */ + if (IntCause & XDP_RX_INTERRUPT_MASK_HDCP_RO_READ_MASK) { + ProcessRoRead(InstancePtr); + } + /* Check for Binfo read */ + if (IntCause & XDP_RX_INTERRUPT_MASK_HDCP_BINFO_READ_MASK) { + ProcessBinfoRead(InstancePtr); + } + + return; +} +#endif + +/*****************************************************************************/ +/** +* +* This tables defines adaptor for DP RX HDCP port driver +* +******************************************************************************/ +const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortDpRxAdaptor = +{ + &XHdcp1x_PortDpRxInit, + &XHdcp1x_PortDpRxEnable, + &XHdcp1x_PortDpRxDisable, + &XHdcp1x_PortDpRxRead, + &XHdcp1x_PortDpRxWrite, + NULL, + NULL, + NULL, + NULL, +// &XHdcp1x_PortDpRxIntrHandler, +}; + +#endif /* defined(XPAR_XDP_RX_NUM_INSTANCES) && (XPAR_XDP_RX_NUM_INSTANCES > 0) */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp_tx.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp_tx.c new file mode 100644 index 00000000..4c99bc3f --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_dp_tx.c @@ -0,0 +1,532 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port_dp_tx.c +* +* This contains the implementation of the HDCP port driver for DP TX +* interfaces +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Fixed link verification handling
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" + +#if defined(XPAR_XDP_NUM_INSTANCES) && (XPAR_XDP_NUM_INSTANCES > 0) +#include "xhdcp1x_port.h" +#include "xhdcp1x_port_dp.h" +#include "xdp.h" +#include "xdp_hw.h" +#include "xil_assert.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This reads a register from the hdcp port device +* +* @param InstancePtr the device to read from +* @param Offset the offset to start reading from +* @param Buf the buffer to copy the data read +* @param BufSize the size of the buffer +* +* @return +* The number of bytes read +* +* @note +* None. +* +******************************************************************************/ +static int RegRead(const XHdcp1x_Port *InstancePtr, u8 Offset, u8 *Buf, + u32 BufSize) +{ + /* Locals */ + XDptx* DpHw = InstancePtr->PhyIfPtr; + u32 Address = 0; + int NumRead = 0; + + /* Determine Address */ + Address = Offset; + Address += 0x68000u; + + /* Read it */ + if (XDp_TxAuxRead(DpHw, Address, BufSize, Buf) == XST_SUCCESS) { + NumRead = BufSize; + } + + /* Return */ + return (NumRead); +} + +/*****************************************************************************/ +/** +* +* This writes a register from the hdcp port device +* +* @param InstancePtr the device to write to +* @param Offset the offset to start writing at +* @param Buf the buffer containing the data to write +* @param BufSize the size of the buffer +* +* @return +* The number of bytes written +* +* @note +* None. +* +******************************************************************************/ +static int RegWrite(XHdcp1x_Port *InstancePtr, u8 Offset, const u8 *Buf, + u32 BufSize) +{ + /* Locals */ + XDptx* DpHw = InstancePtr->PhyIfPtr; + u32 Address = 0; + int NumWritten = 0; + + /* Determine Address */ + Address = Offset; + Address += 0x68000u; + + /* Write it */ + if (XDp_TxAuxWrite(DpHw, Address, BufSize, (u8*) Buf) == XST_SUCCESS) { + NumWritten = BufSize; + } + + /* Return */ + return (NumWritten); +} + +/*****************************************************************************/ +/** +* +* This function checks for a link integrity check failure or re-auth request +* +* @param InstancePtr the device to process the failure +* +* @return +* void +* +* @note +* None +* +******************************************************************************/ +static void CheckForRxStatusChange(XHdcp1x_Port *InstancePtr) +{ + u8 Value = 0; + + /* Read the Bstatus register */ + if (RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Value, 1) > 0) { + u8 ReauthMask = 0; + + /* Determine ReauthMask */ + ReauthMask = XHDCP1X_PORT_BIT_BSTATUS_LINK_FAILURE; + ReauthMask |= XHDCP1X_PORT_BIT_BSTATUS_REAUTH_REQUEST; + + /* Check for link failure or re-authentication requested */ + if ((Value & ReauthMask) != 0) { + /* Invoke authentication callback if set */ + if (InstancePtr->IsAuthCallbackSet) { + (*(InstancePtr->AuthCallback))( + InstancePtr->AuthRef); + } + } + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function enables a hdcp port device +* +* @param InstancePtr the id of the device to enable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxEnable(XHdcp1x_Port *InstancePtr) +{ + u8 Value = 0; + int Status = XST_NOT_ENABLED; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Read anything to ensure that the remote end is present */ + if ((RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1)) > 0) { + Status = XST_SUCCESS; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables a hdcp port device +* +* @param InstancePtr the id of the device to disable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxDisable(XHdcp1x_Port *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Nothing to do at this time */ + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function initializes a hdcp port device +* +* @param InstancePtr the device to initialize +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxInit(XHdcp1x_Port *InstancePtr) +{ + int Status = XST_SUCCESS; + u32 Base = 0; + u32 Value = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Ensure that the dp video path routes through the hdcp core */ + Base = ((XDptx*) InstancePtr->PhyIfPtr)->Config.BaseAddr; + Value = XDptx_ReadReg(Base, XDP_TX_HDCP_ENABLE); + Value |= XDP_TX_HDCP_ENABLE_BYPASS_DISABLE_MASK; + XDptx_WriteReg(Base, XDP_TX_HDCP_ENABLE, Value); + + /* Disable it */ + if (XHdcp1x_PortDpTxDisable(InstancePtr) != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function confirms the presence/capability of the remote hdcp device +* +* @param InstancePtr the device to query +* +* @return +* Truth value +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxIsCapable(const XHdcp1x_Port *InstancePtr) +{ + u8 Value = 0; + int IsCapable = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check for hdcp capable */ + if (RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1) > 0) { + if ((Value & XHDCP1X_PORT_BIT_BCAPS_HDCP_CAPABLE) != 0) { + IsCapable = TRUE; + } + } + + return (IsCapable); +} + +/*****************************************************************************/ +/** +* +* This function confirms if the remote hdcp device is a repeater +* +* @param InstancePtr the device to query +* +* @return +* Truth value +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxIsRepeater(const XHdcp1x_Port *InstancePtr) +{ + u8 Value = 0; + int IsRepeater = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check for repeater */ + if (RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1) > 0) { + if ((Value & XHDCP1X_PORT_BIT_BCAPS_REPEATER) != 0) { + IsRepeater = TRUE; + } + } + + return (IsRepeater); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the repeater information +* +* @param InstancePtr the device to query +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxGetRepeaterInfo(const XHdcp1x_Port *InstancePtr, u16 *Info) +{ + u8 Value = 0; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Info != NULL); + + /* Read the remote capabilities */ + if (RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1) > 0) { + + /* Check for repeater */ + if ((Value & XHDCP1X_PORT_BIT_BCAPS_REPEATER) != 0) { + + /* Read the remote status */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, + &Value, 1); + + /* Check for ready */ + if ((Value & XHDCP1X_PORT_BIT_BSTATUS_READY) != 0) { + + u8 Buf[2]; + u16 U16Value = 0; + + /* Read the Binfo */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BINFO, + Buf, 2); + + /* Determine U16Value */ + XHDCP1X_PORT_BUF_TO_UINT(U16Value, Buf, 16); + + /* Update Info */ + *Info = (U16Value & 0x0FFFu); + + } + else { + Status = XST_DEVICE_BUSY; + } + } + else { + Status = XST_NO_FEATURE; + } + } + else { + Status = XST_RECV_ERROR; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function reads a register from a hdcp port device +* +* @param InstancePtr the device to read from +* @param Offset the offset to start reading from +* @param Buf the buffer to copy the data read +* @param BufSize the size of the buffer +* +* @return +* The number of bytes read +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxRead(const XHdcp1x_Port *InstancePtr, u8 Offset, + void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Read it */ + return (RegRead(InstancePtr, Offset, Buf, BufSize)); +} + +/*****************************************************************************/ +/** +* +* This function writes a register from a hdcp port device +* +* @param InstancePtr the device to write to +* @param Offset the offset to start writing to +* @param Buf the buffer containing the data to write +* @param BufSize the size of the buffer +* +* @return +* The number of bytes written +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortDpTxWrite(XHdcp1x_Port *InstancePtr, u8 Offset, + const void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Write it */ + return (RegWrite(InstancePtr, Offset, Buf, BufSize)); +} + +/*****************************************************************************/ +/** +* +* This handles an interrupt generated by a hdcp port device +* +* @param InstancePtr the device to write to +* @param IntCause the interrupt cause bit map +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_PortDpTxIntrHandler(XHdcp1x_Port *InstancePtr, u32 IntCause) +{ + int HpdDetected = 0; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Determine HpdDetected */ + if (IntCause & XDP_TX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK) { + HpdDetected = TRUE; + } + else if (IntCause & XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK) { + HpdDetected = TRUE; + } + + /* Check for HPD irq */ + if (HpdDetected) { + CheckForRxStatusChange(InstancePtr); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This tables defines the adaptor for the DP TX HDCP port driver +* +******************************************************************************/ +const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortDpTxAdaptor = +{ + &XHdcp1x_PortDpTxInit, + &XHdcp1x_PortDpTxEnable, + &XHdcp1x_PortDpTxDisable, + &XHdcp1x_PortDpTxRead, + &XHdcp1x_PortDpTxWrite, + &XHdcp1x_PortDpTxIsCapable, + &XHdcp1x_PortDpTxIsRepeater, + &XHdcp1x_PortDpTxGetRepeaterInfo, + &XHdcp1x_PortDpTxIntrHandler, +}; + +#endif /* defined(XPAR_XDP_TX_NUM_INSTANCES) && (XPAR_XDP_TX_NUM_INSTANCES > 0) */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi.h new file mode 100644 index 00000000..f80d4606 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi.h @@ -0,0 +1,138 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port_hdmi.h +* +* This file contains the definitions for the hdcp port registers/offsets for +* HDMI interfaces +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +#ifndef XHDCP1X_PORT_HDMI_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_PORT_HDMI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#if defined(XHDCP1X_PORT_DP_H) +#error "cannot include both xhdcp1x_port_dp.h and xhdcp1x_port_hdmi.h" +#endif + +/************************** Constant Definitions *****************************/ + +/** + * These constants specify the offsets for the various fields and/or + * attributes within the hdcp port + */ +#define XHDCP1X_PORT_OFFSET_BKSV (0x00u) /**< Bksv Offset */ +#define XHDCP1X_PORT_OFFSET_RO (0x08u) /**< Ri'/Ro' Offset */ +#define XHDCP1X_PORT_OFFSET_PJ (0x0Au) /**< Pj' Offset */ +#define XHDCP1X_PORT_OFFSET_AKSV (0x10u) /**< Aksv Offset */ +#define XHDCP1X_PORT_OFFSET_AINFO (0x15u) /**< Ainfo Offset */ +#define XHDCP1X_PORT_OFFSET_AN (0x18u) /**< An Offset */ +#define XHDCP1X_PORT_OFFSET_VH0 (0x20u) /**< V'.H0 Offset */ +#define XHDCP1X_PORT_OFFSET_VH1 (0x24u) /**< V'.H1 Offset */ +#define XHDCP1X_PORT_OFFSET_VH2 (0x28u) /**< V'.H2 Offset */ +#define XHDCP1X_PORT_OFFSET_VH3 (0x2Cu) /**< V'.H3 Offset */ +#define XHDCP1X_PORT_OFFSET_VH4 (0x30u) /**< V'.H4 Offset */ +#define XHDCP1X_PORT_OFFSET_BCAPS (0x40u) /**< Bcaps Offset */ +#define XHDCP1X_PORT_OFFSET_BSTATUS (0x41u) /**< Bstatus Offset */ +#define XHDCP1X_PORT_OFFSET_KSVFIFO (0x43u) /**< KSV FIFO Offset */ +#define XHDCP1X_PORT_OFFSET_DBG (0xC0u) /**< Debug Space Offset */ + +/** + * These constants specify the sizes for the various fields and/or + * attributes within the hdcp port + */ +#define XHDCP1X_PORT_SIZE_BKSV (0x05u) /**< Bksv Size */ +#define XHDCP1X_PORT_SIZE_RO (0x02u) /**< Ri' Size */ +#define XHDCP1X_PORT_SIZE_PJ (0x01u) /**< Pj' Size */ +#define XHDCP1X_PORT_SIZE_AKSV (0x05u) /**< Aksv Size */ +#define XHDCP1X_PORT_SIZE_AINFO (0x01u) /**< Ainfo Size */ +#define XHDCP1X_PORT_SIZE_AN (0x08u) /**< An Size */ +#define XHDCP1X_PORT_SIZE_VH0 (0x04u) /**< V'.H0 Size */ +#define XHDCP1X_PORT_SIZE_VH1 (0x04u) /**< V'.H1 Size */ +#define XHDCP1X_PORT_SIZE_VH2 (0x04u) /**< V'.H2 Size */ +#define XHDCP1X_PORT_SIZE_VH3 (0x04u) /**< V'.H3 Size */ +#define XHDCP1X_PORT_SIZE_VH4 (0x04u) /**< V'.H4 Size */ +#define XHDCP1X_PORT_SIZE_BCAPS (0x01u) /**< Bcaps Size */ +#define XHDCP1X_PORT_SIZE_BSTATUS (0x02u) /**< Bstatus Size */ +#define XHDCP1X_PORT_SIZE_KSVFIFO (0x01u) /**< KSV FIFO Size */ +#define XHDCP1X_PORT_SIZE_DBG (0xC0u) /**< Debug Space Size */ + +/** + * These constants specify the bit definitions within the various fields + * and/or attributes within the hdcp port + */ +#define XHDCP1X_PORT_BIT_BSTATUS_HDMI_MODE (1u << 12) + +#define XHDCP1X_PORT_BIT_BCAPS_FAST_REAUTH (1u << 0) +#define XHDCP1X_PORT_BIT_BCAPS_1d1_FEATURES (1u << 1) +#define XHDCP1X_PORT_BIT_BCAPS_FAST (1u << 4) +#define XHDCP1X_PORT_BIT_BCAPS_READY (1u << 5) +#define XHDCP1X_PORT_BIT_BCAPS_REPEATER (1u << 6) +#define XHDCP1X_PORT_BIT_BCAPS_HDMI (1u << 7) + +#define XHDCP1X_PORT_BIT_AINFO_ENABLE_1d1_FEATURES (1u << 1) + +/** + * This constant defines the i2c address of the hdcp port + */ +#define XHDCP1X_PORT_PRIMARY_I2C_ADDR (0x74u) /**< I2C Addr Primary Link */ +#define XHDCP1X_PORT_SECONDARY_I2C_ADDR (0x76u) /**< I2C Addr Secondary Link*/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* XHDCP1X_PORT_HDMI_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi_rx.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi_rx.c new file mode 100644 index 00000000..482600ea --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi_rx.c @@ -0,0 +1,424 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port_hdmi_rx.c +* +* This contains the implementation of the HDCP port driver for HDMI RX +* interfaces +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" + +#if defined(XPAR_XHDMI_RX_NUM_INSTANCES) && (XPAR_XHDMI_RX_NUM_INSTANCES > 0) +#include +#include +#include "xhdcp1x_port.h" +#include "xhdcp1x_port_hdmi.h" +#include "xhdmi_rx.h" +#include "xil_assert.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This reads a register from the hdcp port device +* +* @param InstancePtr the device to read from +* @param Offset the offset to start reading from +* @param Buf the Bufer to copy the data read +* @param BufSize the size of the Bufer +* +* @return +* The number of bytes read +* +* @note +* None. +* +******************************************************************************/ +static int RegRead(const XHdcp1x_Port *InstancePtr, u8 Offset, u8 *Buf, + u32 BufSize) +{ + /* Locals */ + XHdmi_Rx *HdmiRx = InstancePtr->PhyIfPtr; + u32 NumLeft = BufSize; + + /* Write the offset */ + XHdmiRx_DdcHdcpSetAddress(HdmiRx, Offset); + + /* Read the buffer */ + while (NumLeft-- > 0) { + *Buf++ = XHdmiRx_DdcHdcpReadData(HdmiRx); + } + + /* Return */ + return ((int) BufSize); +} + +/*****************************************************************************/ +/** +* +* This writes a register from the hdcp port device +* +* @param InstancePtr the device to write to +* @param Offset the offset to start writing at +* @param Buf the Bufer containing the data to write +* @param BufSize the size of the Bufer +* +* @return +* The number of bytes written +* +* @note +* None. +* +******************************************************************************/ +static int RegWrite(XHdcp1x_Port *InstancePtr, u8 Offset, const u8 *Buf, + u32 BufSize) +{ + XHdmi_Rx *HdmiRx = InstancePtr->PhyIfPtr; + u32 NumLeft = BufSize; + + /* Write the offset */ + XHdmiRx_DdcHdcpSetAddress(HdmiRx, Offset); + + /* Write the buffer */ + while (NumLeft-- > 0) { + XHdmiRx_DdcHdcpWriteData(HdmiRx, *Buf++); + } + + /* Return */ + return ((int) BufSize); +} + +/*****************************************************************************/ +/** +* +* This function process a write to the AKsv register from the tx device +* +* @param CallbackRef the device to whose register was written +* +* @return +* void +* +* @note +* This function initiates the side effects of the tx device writing the Aksv +* register. This is currently updates some status bits as well as kick +* starts a re-authentication process. +* +******************************************************************************/ +static void ProcessAKsvWrite(void *CallbackRef) +{ + XHdcp1x_Port *InstancePtr = (XHdcp1x_Port *) CallbackRef; + u8 Value = 0; + + /* Update statistics */ + InstancePtr->Stats.IntCount++; + + /* Clear bit 1 of the Ainfo register */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_AINFO, &Value, 1); + Value &= 0xFDu; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_AINFO, &Value, 1); + + /* Invoke authentication callback if set */ + if (InstancePtr->IsAuthCallbackSet) { + (*(InstancePtr->AuthCallback))(InstancePtr->AuthRef); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function enables a hdcp port device +* +* @param InstancePtr the id of the device to enable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiRxEnable(XHdcp1x_Port *InstancePtr) +{ + XHdmi_Rx *HdmiRx = NULL; + u8 Buf[4]; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Determine HdmiRx */ + HdmiRx = InstancePtr->PhyIfPtr; + + /* Initialize the Bstatus register */ + memset(Buf, 0, 4); + Buf[1] |= (XHDCP1X_PORT_BIT_BSTATUS_HDMI_MODE >> 8); + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, 2); + + /* Initialize the Bcaps register */ + memset(Buf, 0, 4); + Buf[0] |= XHDCP1X_PORT_BIT_BCAPS_HDMI; + Buf[0] |= XHDCP1X_PORT_BIT_BCAPS_FAST_REAUTH; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, Buf, 1); + + /* Initialize some debug registers */ + Buf[0] = 0xDE; + Buf[1] = 0xAD; + Buf[2] = 0xBE; + Buf[3] = 0xEF; + RegWrite(InstancePtr, XHDCP1X_PORT_OFFSET_DBG, Buf, 4); + + /* Bind for interrupt callback */ + XHdmiRx_SetCallback(HdmiRx, XHDMI_RX_HANDLER_HDCP, + ProcessAKsvWrite, InstancePtr); + + /* Enable the hdcp slave over the ddc */ + XHdmiRx_DdcHdcpEnable(HdmiRx); + XHdmiRx_DdcIntrEnable(HdmiRx); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables a hdcp port device +* +* @param InstancePtr the id of the device to disable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiRxDisable(XHdcp1x_Port *InstancePtr) +{ + u8 Offset = 0; + u8 U8Value = 0; + u32 HdmiRxBase = 0; + u32 Value; + int NumLeft = 0; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Determine HdmiRxBase */ + HdmiRxBase = ((XHdmi_Rx*) InstancePtr->PhyIfPtr)->Config.BaseAddress; + + /* Disable the hdcp ddc slave */ + Value = XHdmiRx_ReadReg(HdmiRxBase, XHDMI_RX_DDC_CTRL_SET_OFFSET); + Value &= ~XHDMI_RX_DDC_CTRL_HDCP_EN_MASK; + XHdmiRx_WriteReg(HdmiRxBase, XHDMI_RX_DDC_CTRL_SET_OFFSET, Value); + + /* Clear the hdcp registers */ + U8Value = 0; + Offset = 0; + NumLeft = 256; + while (NumLeft-- > 0) { + RegWrite(InstancePtr, Offset++, &U8Value, 1); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function initializes a hdcp port device +* +* @param InstancePtr the device to initialize +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiRxInit(XHdcp1x_Port *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Disable it */ + if (XHdcp1x_PortHdmiRxDisable(InstancePtr) != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function reads a register from a hdcp port device +* +* @param InstancePtr the device to read from +* @param Offset the offset to start reading from +* @param Buf the Bufer to copy the data read +* @param BufSize the size of the Bufer +* +* @return +* The number of bytes read +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiRxRead(const XHdcp1x_Port *InstancePtr, u8 Offset, + void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Read it */ + return (RegRead(InstancePtr, Offset, Buf, BufSize)); +} + +/*****************************************************************************/ +/** +* +* This function writes a register from a hdcp port device +* +* @param InstancePtr the device to write to +* @param Offset the offset to start writing to +* @param Buf the Bufer containing the data to write +* @param BufSize the size of the Bufer +* +* @return +* The number of bytes written +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiRxWrite(XHdcp1x_Port *InstancePtr, u8 Offset, + const void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Write it */ + return (RegWrite(InstancePtr, Offset, Buf, BufSize)); +} + +#if 0 +/*****************************************************************************/ +/** +* +* This function serves as the interrupt handler for the hdcp port device +* +* @param CallbackRef the device that generated the interrupt +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_PortHdmiRxIntrHandler(XHdcp1x_Port *InstancePtr, u32 IntCause) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Process the Aksv write as it is the only hdcp interrupt */ + ProcessAKsvWrite(InstancePtr); + + /* Return */ + return; +} +#endif + +/*****************************************************************************/ +/** +* +* This tables defines the adaptor for the HDMI RX HDCP port driver +* +******************************************************************************/ +const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortHdmiRxAdaptor = +{ + &XHdcp1x_PortHdmiRxInit, + &XHdcp1x_PortHdmiRxEnable, + &XHdcp1x_PortHdmiRxDisable, + &XHdcp1x_PortHdmiRxRead, + &XHdcp1x_PortHdmiRxWrite, + NULL, + NULL, + NULL, + NULL, +// &XHdcp1x_PortHdmiRxIntrHandler, +}; + +#endif /* defined(XPAR_XHDMI_RX_NUM_INSTANCES) && (XPAR_XHDMI_RX_NUM_INSTANCES > 0) */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi_tx.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi_tx.c new file mode 100644 index 00000000..468d08af --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_hdmi_tx.c @@ -0,0 +1,465 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port_hdmi_tx.c +* +* This contains the implementation of the HDCP port driver for HDMI TX +* interfaces +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" + +#if defined(XPAR_XHDMI_TX_NUM_INSTANCES) && (XPAR_XHDMI_TX_NUM_INSTANCES > 0) +#include +#include +#include "xhdcp1x_port.h" +#include "xhdcp1x_port_hdmi.h" +#include "xhdmi_tx.h" +#include "xil_assert.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#define WRITE_CHUNK_SZ (8) + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This reads a register from the hdcp port device +* +* @param InstancePtr the device to read from +* @param Offdry the offset to start reading from +* @param Buf the buffer to copy the data read +* @param BufSize the size of the buffer +* +* @return +* The number of bytes read +* +* @note +* None. +* +******************************************************************************/ +static int RegRead(const XHdcp1x_Port *InstancePtr, u8 Offset, u8 *Buf, + u32 BufSize) +{ + XHdmi_Tx* HdmiTx = InstancePtr->PhyIfPtr; + u8 Slave = 0x3Au; + int NumRead = 0; + + /* Write the address and check for failure */ + if (XHdmiTx_DdcWrite(HdmiTx, Slave, 1, &Offset, FALSE) + != XST_SUCCESS) { + NumRead = -1; + } + /* Read the data back and check for failure */ + else if (XHdmiTx_DdcRead(HdmiTx, Slave, BufSize, Buf, TRUE) + != XST_SUCCESS) { + NumRead = -2; + } + /* Success - just update NumRead */ + else { + NumRead = (int) BufSize; + } + + return (NumRead); +} + +/*****************************************************************************/ +/** +* +* This writes a register from the hdcp port device +* +* @param InstancePtr the device to write to +* @param Offset the offset to start writing at +* @param Buf the buffer containing the data to write +* @param BufSize the size of the buffer +* +* @return +* The number of bytes written +* +* @note +* None. +* +******************************************************************************/ +static int RegWrite(XHdcp1x_Port *InstancePtr, u8 Offset, const u8 *Buf, + u32 BufSize) +{ + XHdmi_Tx* HdmiTx = InstancePtr->PhyIfPtr; + u8 Slave = 0x3Au; + u8 TxBuf[WRITE_CHUNK_SZ+1]; + int NumWritten = 0; + int ThisTime = 0; + + /* Iterate through the buffer */ + do { + /* Determine ThisTime */ + ThisTime = WRITE_CHUNK_SZ; + if (ThisTime > BufSize) { + ThisTime = BufSize; + } + + /* Format TxBuf */ + TxBuf[0] = Offset; + memcpy(&(TxBuf[1]), Buf, ThisTime); + + /* Write the TxBuf */ + if (XHdmiTx_DdcWrite(HdmiTx, Slave, (ThisTime+1), TxBuf, TRUE) + != XST_SUCCESS) { + /* Update NumWritten and break */ + NumWritten = -1; + break; + } + + /* Update for loop */ + NumWritten += ThisTime; + Buf += ThisTime; + BufSize -= ThisTime; + + } while ((BufSize != 0) && (NumWritten > 0)); + + /* Return */ + return (NumWritten); +} + +/*****************************************************************************/ +/** +* +* This function enables a hdcp port device +* +* @param InstancePtr the id of the device to enable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxEnable(XHdcp1x_Port *InstancePtr) +{ + u8 Value = 0; + int Status = XST_NOT_ENABLED; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Read anything to ensure that the remote end is present */ + if ((RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1)) > 0) { + Status = XST_SUCCESS; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables a hdcp port device +* +* @param InstancePtr the id of the device to disable +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxDisable(XHdcp1x_Port *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Nothing to do at this time */ + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function initializes a hdcp port device +* +* @param InstancePtr the device to initialize +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxInit(XHdcp1x_Port *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->PhyIfPtr != NULL); + + /* Disable it */ + if (XHdcp1x_PortHdmiTxDisable(InstancePtr) != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function confirms the presence/capability of the remote hdcp device +* +* @param InstancePtr the device to query +* +* @return +* Truth value +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxIsCapable(const XHdcp1x_Port *InstancePtr) +{ + u8 Value = 0; + int IsCapable = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check for hdcp capable */ + if (RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1) > 0) { + if ((Value & XHDCP1X_PORT_BIT_BCAPS_HDMI) != 0) { + IsCapable = TRUE; + } + } + + return (IsCapable); +} + +/*****************************************************************************/ +/** +* +* This function confirms if the remote hdcp device is a repeater +* +* @param InstancePtr the device to query +* +* @return +* Truth value +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxIsRepeater(const XHdcp1x_Port *InstancePtr) +{ + u8 Value = 0; + int IsRepeater = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check for repeater */ + if (RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1) > 0) { + if ((Value & XHDCP1X_PORT_BIT_BCAPS_REPEATER) != 0) { + IsRepeater = TRUE; + } + } + + return (IsRepeater); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the repeater information +* +* @param InstancePtr the device to query +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxGetRepeaterInfo(const XHdcp1x_Port *InstancePtr, u16 *Info) +{ + u8 Value = 0; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Info != NULL); + + /* Read the remote capabilities */ + if (RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, &Value, 1) > 0) { + + u8 ReadyMask = 0; + + /* Determine ReadyMask */ + ReadyMask = XHDCP1X_PORT_BIT_BCAPS_REPEATER; + ReadyMask |= XHDCP1X_PORT_BIT_BCAPS_READY; + + /* Check for repeater and ksv fifo ready */ + if ((Value & ReadyMask) == ReadyMask) { + + u8 Buf[2]; + u16 U16Value = 0; + + /* Read the Bstatus */ + RegRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, + Buf, 2); + + /* Determine Value */ + XHDCP1X_PORT_BUF_TO_UINT(U16Value, Buf, 16); + + /* Update Info */ + *Info = (U16Value & 0x0FFFu); + } + else { + Status = XST_DEVICE_BUSY; + } + } + else { + Status = XST_RECV_ERROR; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function reads a register from a hdcp port device +* +* @param InstancePtr the device to read from +* @param Offset the offset to start reading from +* @param Buf the buffer to copy the data read +* @param BufSize the size of the buffer +* +* @return +* The number of bytes read +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxRead(const XHdcp1x_Port* InstancePtr, u8 Offset, + void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Read it */ + return (RegRead(InstancePtr, Offset, Buf, BufSize)); +} + +/*****************************************************************************/ +/** +* +* This function writes a register from a hdcp port device +* +* @param InstancePtr the device to write to +* @param Offset the offset to start writing to +* @param Buf the buffer containing the data to write +* @param BufSize the size of the buffer +* +* @return +* The number of bytes written +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_PortHdmiTxWrite(XHdcp1x_Port *InstancePtr, u8 Offset, + const void *Buf, u32 BufSize) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(Buf != NULL); + + /* Truncate if necessary */ + if ((BufSize + Offset) > 0x100u) { + BufSize = (0x100u - Offset); + } + + /* Write it */ + return (RegWrite(InstancePtr, Offset, Buf, BufSize)); +} + +/*****************************************************************************/ +/** +* +* This tables defines the adaptor for the HDMI TX HDCP port driver +* +******************************************************************************/ +const XHdcp1x_PortPhyIfAdaptor XHdcp1x_PortHdmiTxAdaptor = +{ + &XHdcp1x_PortHdmiTxInit, + &XHdcp1x_PortHdmiTxEnable, + &XHdcp1x_PortHdmiTxDisable, + &XHdcp1x_PortHdmiTxRead, + &XHdcp1x_PortHdmiTxWrite, + &XHdcp1x_PortHdmiTxIsCapable, + &XHdcp1x_PortHdmiTxIsRepeater, + &XHdcp1x_PortHdmiTxGetRepeaterInfo, + NULL, +}; + +#endif /* defined(XPAR_XHDMI_TX_NUM_INSTANCES) && (XPAR_XHDMI_TX_NUM_INSTANCES > 0) */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_intr.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_intr.c new file mode 100644 index 00000000..87110c52 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_port_intr.c @@ -0,0 +1,151 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_port_intr.c +* +* This contains the interrupt related functions of the Xilinx HDCP port driver +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xhdcp1x_port.h" +#include "xil_assert.h" +#include "xil_types.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function installs an asynchronous callback function for the given +* HandlerType: +* +*
+* HandlerType                           Callback Function Type
+* ------------------------------------  -------------------------------------
+* (XHDCP1X_PORT_HANDLER_AUTHENTICATE)   AuthCallback
+* 
+* +* @param InstancePtr is a pointer to the HDCP port instance. +* @param HandlerType specifies the type of handler. +* @param CallbackFunc is the address of the callback function. +* @param CallbackRef is a user data item that will be passed to the +* callback function when it is invoked. +* +* @return +* - XST_SUCCESS if callback function installed successfully. +* - XST_INVALID_PARAM when HandlerType is invalid. +* +* @note Invoking this function for a handler that already has been +* installed replaces it with the new handler. +* +******************************************************************************/ +int XHdcp1x_PortSetCallback(XHdcp1x_Port *InstancePtr, u32 HandlerType, + XHdcp1x_Callback CallbackFunc, void *CallbackRef) +{ + u32 Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(HandlerType >= (XHDCP1X_PORT_HANDLER_AUTHENTICATE)); + Xil_AssertNonvoid(CallbackFunc != NULL); + Xil_AssertNonvoid(CallbackRef != NULL); + + /* Check for handler type */ + switch (HandlerType) { + + /* Authentication Callback */ + case (XHDCP1X_PORT_HANDLER_AUTHENTICATE): + InstancePtr->AuthCallback = CallbackFunc; + InstancePtr->AuthRef = CallbackRef; + InstancePtr->IsAuthCallbackSet = (TRUE); + break; + + default: + Status = (XST_INVALID_PARAM); + break; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This handles an interrupt generated by a hdcp port device +* +* @param InstancePtr the device to write to +* @param IntCause the interrupt cause bit map +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_PortHandleInterrupt(XHdcp1x_Port *InstancePtr, u32 IntCause) +{ + const XHdcp1x_PortPhyIfAdaptor *Adaptor = NULL; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Determine Adaptor */ + Adaptor = InstancePtr->Adaptor; + + /* Check for adaptor function and invoke if present*/ + if ((Adaptor != NULL) && (Adaptor->IntrHandler != NULL)) { + InstancePtr->Stats.IntCount++; + (*(Adaptor->IntrHandler))(InstancePtr, IntCause); + } + + return; +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_rx.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_rx.c new file mode 100644 index 00000000..3e7dceef --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_rx.c @@ -0,0 +1,1537 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_rx.c +* +* This contains the main implementation file for the Xilinx HDCP receive state +* machine +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +*****************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" + +#include +#include +#include +#include "xhdcp1x.h" +#include "xhdcp1x_cipher.h" +#include "xhdcp1x_debug.h" +#include "xhdcp1x_port.h" +#if defined(XPAR_XHDMI_RX_NUM_INSTANCES) && (XPAR_XHDMI_RX_NUM_INSTANCES > 0) + #include "xhdcp1x_port_hdmi.h" +#else + #include "xhdcp1x_port_dp.h" +#endif +#include "xhdcp1x_rx.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#define FLAG_PHY_UP (1u << 0) /**< Flag to track physical state */ + +/**************************** Type Definitions *******************************/ +typedef enum +{ + EVENT_NULL, + EVENT_AUTHENTICATE, + EVENT_CHECK, + EVENT_DISABLE, + EVENT_ENABLE, + EVENT_PHYDOWN, + EVENT_PHYUP, + EVENT_POLL, + EVENT_UPDATERi, + +} tEvent; + +typedef enum +{ + STATE_DISABLED, + STATE_UNAUTHENTICATED, + STATE_COMPUTATIONS, + STATE_AUTHENTICATED, + STATE_LINKINTEGRITYFAILED, + STATE_PHYDOWN, + +} tState; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is Display Port (DP) +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating DP (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsDP(InstancePtr) (!InstancePtr->CfgPtr->IsHDMI) + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is HDMI +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating HDMI (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsHDMI(InstancePtr) (InstancePtr->CfgPtr->IsHDMI) + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function logs a debug message on behalf of a handler state machine +* +* @param InstancePtr the receiver instance +* @param LogMsg the message to log +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void DebugLog(const XHdcp1x_Rx *InstancePtr, const char *LogMsg) +{ + char Label[16]; + + /* Format Label */ + snprintf(Label, 16, "hdcp-rx(%d) - ", InstancePtr->CfgPtr->DeviceId); + + /* Log it */ + XHDCP1X_DEBUG_LOGMSG(Label); + XHDCP1X_DEBUG_LOGMSG(LogMsg); + XHDCP1X_DEBUG_LOGMSG("\r\n"); + + return; +} + +/*****************************************************************************/ +/** +* +* This function posts an event to a state machine +* +* @param InstancePtr the receiver instance +* @param Event the event to post +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void PostEvent(XHdcp1x_Rx *InstancePtr, tEvent Event) +{ + /* Check for disable and clear any pending enable */ + if (Event == EVENT_DISABLE) { + InstancePtr->PendingEvents &= ~(1u << EVENT_ENABLE); + } + /* Check for phy-down and clear any pending phy-up */ + else if (Event == EVENT_PHYDOWN) { + InstancePtr->PendingEvents &= ~(1u << EVENT_PHYUP); + } + + /* Post it */ + InstancePtr->PendingEvents |= (1u << Event); + + return; +} + +/*****************************************************************************/ +/** +* +* This function acts as the re-authentication callback for a state machine +* +* @param Parameter the parameter specified during registration +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void AuthCallback(void *Parameter) +{ + XHdcp1x_Rx *InstancePtr = Parameter; + + /* Post the re-authentication request */ + PostEvent(InstancePtr, EVENT_AUTHENTICATE); + + return; +} + +/*****************************************************************************/ +/** +* +* This function acts as the link failure callback for a state machine +* +* @param Parameter the parameter specified during registration +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void LinkFailCallback(void *Parameter) +{ + XHdcp1x_Rx *InstancePtr = Parameter; + + /* Post the check request */ + PostEvent(InstancePtr, EVENT_CHECK); + + return; +} + +/*****************************************************************************/ +/** +* +* This function acts as the Ri register update callback for a state machine +* +* @param Parameter the parameter specified during registration +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RiUpdateCallback(void *Parameter) +{ + XHdcp1x_Rx *InstancePtr = Parameter; + + /* Post the update Ri request */ + PostEvent(InstancePtr, EVENT_UPDATERi); + + return; +} + +/*****************************************************************************/ +/** +* +* This function sets the check link state of the handler +* +* @param InstancePtr the receiver instance +* @param IsEnabled truth value indicating on/off +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void SetCheckLinkState(XHdcp1x_Rx *InstancePtr, int IsEnabled) +{ + XHdcp1x_Cipher *CipherPtr = &(InstancePtr->Cipher); + + /* Check for DP */ + if (IsDP(InstancePtr)) { + XHdcp1x_CipherSetLinkStateCheck(CipherPtr, IsEnabled); + } + /* Check for HDMI */ + else if (IsHDMI(InstancePtr)) { + XHdcp1x_CipherSetRiUpdate(CipherPtr, IsEnabled); + } + + /* Return */ + return; +} + +/*****************************************************************************/ +/** +* +* This function enables a receiver state machine +* +* @param InstancePtr the receiver instance +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Enable(XHdcp1x_Rx *InstancePtr) +{ + XHdcp1x_Cipher *CipherPtr = &(InstancePtr->Cipher); + XHdcp1x_Port *PortPtr = &(InstancePtr->Port); + u64 MyKsv = 0; + u8 Buf[8]; + + /* Disable and register the link failure callback */ + XHdcp1x_CipherSetLinkStateCheck(CipherPtr, FALSE); + XHdcp1x_CipherSetCallback(CipherPtr, + XHDCP1X_CIPHER_HANDLER_LINK_FAILURE, + &LinkFailCallback, InstancePtr); + + /* Disable and register the Ri callback */ + XHdcp1x_CipherSetRiUpdate(CipherPtr, FALSE); + XHdcp1x_CipherSetCallback(CipherPtr, + XHDCP1X_CIPHER_HANDLER_Ri_UPDATE, + &RiUpdateCallback, InstancePtr); + + /* Enable the crypto engine */ + XHdcp1x_CipherEnable(CipherPtr); + + /* Read MyKsv */ + MyKsv = XHdcp1x_CipherGetLocalKsv(CipherPtr); + + /* If unknown - try against for good luck */ + if (MyKsv == 0) { + MyKsv = XHdcp1x_CipherGetLocalKsv(CipherPtr); + } + + /* Initialize Bksv */ + memset(Buf, 0, 8); + XHDCP1X_PORT_UINT_TO_BUF(Buf, MyKsv, XHDCP1X_PORT_SIZE_BKSV*8); + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_BKSV, Buf, + XHDCP1X_PORT_SIZE_BKSV); + + /* Register the re-authentication callback */ + XHdcp1x_PortSetCallback(PortPtr, XHDCP1X_PORT_HANDLER_AUTHENTICATE, + &AuthCallback, InstancePtr); + + /* Enable the hdcp port */ + XHdcp1x_PortEnable(PortPtr); + + return; +} + +/*****************************************************************************/ +/** +* +* This function disables a receiver state machine +* +* @param InstancePtr the receiver instance +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Disable(XHdcp1x_Rx *InstancePtr) +{ + /* Disable the hdcp cipher and port */ + XHdcp1x_PortDisable(&(InstancePtr->Port)); + XHdcp1x_CipherDisable(&(InstancePtr->Cipher)); + + /* Clear statistics */ + memset(&(InstancePtr->Stats), 0, sizeof(InstancePtr->Stats)); + + return; +} + +/*****************************************************************************/ +/** +* +* This function initiates the computations for a receiver state machine +* +* @param InstancePtr the receiver instance +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void StartComputations(XHdcp1x_Rx *InstancePtr, tState *NextStatePtr) +{ + XHdcp1x_Cipher *CipherPtr = &(InstancePtr->Cipher); + XHdcp1x_Port *PortPtr = &(InstancePtr->Port); + u8 Buf[8]; + u64 Value = 0; + u32 X = 0; + u32 Y = 0; + u32 Z = 0; + + /* Log */ + DebugLog(InstancePtr, "starting computations"); + + /* Update statistics */ + InstancePtr->Stats.AuthAttempts++; + + /* Determine theAKsv */ + memset(Buf, 0, 8); + XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_AKSV, Buf, + XHDCP1X_PORT_SIZE_AKSV); + XHDCP1X_PORT_BUF_TO_UINT(Value, Buf, XHDCP1X_PORT_SIZE_AKSV*8); + + /* Load the cipher with the remote ksv */ + XHdcp1x_CipherSetRemoteKsv(CipherPtr, Value); + + /* Update theU64Value with An */ + memset(Buf, 0, 8); + XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_AN, Buf, + XHDCP1X_PORT_SIZE_AN); + XHDCP1X_PORT_BUF_TO_UINT(Value, Buf, XHDCP1X_PORT_SIZE_AN*8); + + /* Load the cipher B registers with An */ + X = (u32) (Value & 0x0FFFFFFFul); + Value >>= 28; + Y = (u32) (Value & 0x0FFFFFFFul); + Value >>= 28; + Z = (u32) (Value & 0x000000FFul); + XHdcp1x_CipherSetB(CipherPtr, X, Y, Z); + + /* Initiate the block cipher */ + XHdcp1x_CipherDoRequest(CipherPtr, XHDCP1X_CIPHER_REQUEST_BLOCK); + + /* Return */ + return; +} + +/*****************************************************************************/ +/** +* +* This function polls the progress of the computations for a state machine +* +* @param InstancePtr the receiver instance +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void PollForComputations(XHdcp1x_Rx *InstancePtr, tState *NextStatePtr) +{ + XHdcp1x_Cipher *CipherPtr = &(InstancePtr->Cipher); + + /* Check for done */ + if (XHdcp1x_CipherIsRequestComplete(CipherPtr)) { + XHdcp1x_Port *PortPtr = &(InstancePtr->Port); + u8 Buf[4]; + u16 Ro = 0; + + /* Log */ + DebugLog(InstancePtr, "computations complete"); + + /* Read theRo */ + Ro = XHdcp1x_CipherGetRo(CipherPtr); + + /* Initialize Buf */ + memset(Buf, 0, 4); + XHDCP1X_PORT_UINT_TO_BUF(Buf, Ro, 16); + + /* Update the value of Ro' */ + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_RO, Buf, 2); + +#if defined(XHDCP1X_PORT_BIT_BSTATUS_RO_AVAILABLE) + /* Update the Bstatus to indicate Ro' available */ + XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, + XHDCP1X_PORT_SIZE_BSTATUS); + Buf[0] |= XHDCP1X_PORT_BIT_BSTATUS_RO_AVAILABLE; + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, + XHDCP1X_PORT_SIZE_BSTATUS); +#endif + + /* Update NextStatePtr */ + *NextStatePtr = STATE_AUTHENTICATED; + } + else { + DebugLog(InstancePtr, "waiting for computations"); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function updates the Ro'/Ri' register of the state machine +* +* @param InstancePtr the receiver instance +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* This function has to save the value of Ri (in RememberRi) as the macro +* that converts from a uint16 to a HDCP buffer destroys the original value +* +******************************************************************************/ +static void UpdateRi(XHdcp1x_Rx *InstancePtr, tState *NextStatePtr) +{ + XHdcp1x_Cipher *CipherPtr = &(InstancePtr->Cipher); + XHdcp1x_Port *PortPtr = &(InstancePtr->Port); + char LogBuf[20]; + u8 Buf[4]; + u16 Ri = 0; + u16 RememberRi = 0; + + /* Read Ri */ + Ri = XHdcp1x_CipherGetRi(CipherPtr); + + /* Update RememberRi */ + RememberRi = Ri; + + /* Initialize theBuf */ + memset(Buf, 0, 4); + XHDCP1X_PORT_UINT_TO_BUF(Buf, Ri, XHDCP1X_PORT_SIZE_RO*8); + + /* Update the value of Ro' */ + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_RO, Buf, sizeof(Ri)); + +#if defined(XHDCP1X_PORT_BIT_BSTATUS_RO_AVAILABLE) + /* Update the Bstatus to indicate Ro' available */ + XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, + XHDCP1X_PORT_SIZE_BSTATUS); + Buf[0] |= XHDCP1X_PORT_BIT_BSTATUS_RO_AVAILABLE; + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, + XHDCP1X_PORT_SIZE_BSTATUS); +#endif + + /* Update statistics */ + InstancePtr->Stats.RiUpdates++; + + /* Determine theLogBuf */ + snprintf(LogBuf, 20, "update Ri (%04X)", RememberRi); + + /* Log */ + DebugLog(InstancePtr, LogBuf); + + return; +} + +/*****************************************************************************/ +/** +* +* This functions handles check the integrity of the link +* +* @param InstancePtr the receiver instance +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None +* +******************************************************************************/ +static void CheckLinkIntegrity(XHdcp1x_Rx *InstancePtr, tState *NextStatePtr) +{ + if (XHdcp1x_CipherIsLinkUp(&(InstancePtr->Cipher))) { + *NextStatePtr = STATE_AUTHENTICATED; + } + else { + *NextStatePtr = STATE_LINKINTEGRITYFAILED; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This functions reports the failure of link integrity +* +* @param InstancePtr the receiver instance +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None +* +******************************************************************************/ +static void ReportLinkIntegrityFailure(XHdcp1x_Rx *InstancePtr, + tState *NextStatePtr) +{ +#if defined(XHDCP1X_PORT_BIT_BSTATUS_LINK_FAILURE) + XHdcp1x_Port *PortPtr = &(InstancePtr->Port); + u8 Buf[XHDCP1X_PORT_SIZE_BSTATUS]; + + /* Update the Bstatus register */ + XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, + XHDCP1X_PORT_SIZE_BSTATUS); + Buf[0] |= XHDCP1X_PORT_BIT_BSTATUS_LINK_FAILURE; + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_BSTATUS, Buf, + XHDCP1X_PORT_SIZE_BSTATUS); +#endif + + /* Log */ + DebugLog(InstancePtr, "link integrity failed"); + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "disabled" state of the receiver state machine +* +* @param InstancePtr the receiver instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunDisabledState(XHdcp1x_Rx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For enable */ + case EVENT_ENABLE: + *NextStatePtr = STATE_UNAUTHENTICATED; + if ((InstancePtr->Flags & FLAG_PHY_UP) == 0) + *NextStatePtr = STATE_PHYDOWN; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + InstancePtr->Flags &= ~FLAG_PHY_UP; + break; + /* For physical layer up */ + case EVENT_PHYUP: + InstancePtr->Flags |= FLAG_PHY_UP; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "unauthenticated" state of the receiver state machine +* +* @param InstancePtr the receiver instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunUnauthenticatedState(XHdcp1x_Rx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_COMPUTATIONS; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "computations" state of the receiver state machine +* +* @param InstancePtr the receiver instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunComputationsState(XHdcp1x_Rx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + StartComputations(InstancePtr, NextStatePtr); + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* For poll */ + case EVENT_POLL: + PollForComputations(InstancePtr, NextStatePtr); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "authenticated" state of the receiver state machine +* +* @param InstancePtr the receiver instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunAuthenticatedState(XHdcp1x_Rx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_COMPUTATIONS; + break; + /* For check */ + case EVENT_CHECK: + CheckLinkIntegrity(InstancePtr, NextStatePtr); + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* For update Ri */ + case EVENT_UPDATERi: + UpdateRi(InstancePtr, NextStatePtr); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "link integrity failed" state of the receiver state +* machine +* +* @param InstancePtr the receiver instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunLinkIntegrityFailedState(XHdcp1x_Rx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_COMPUTATIONS; + break; + /* For check */ + case EVENT_CHECK: + CheckLinkIntegrity(InstancePtr, NextStatePtr); + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "physical layer down" state of the receiver state +* machine +* +* @param InstancePtr the receiver instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunPhysicalLayerDownState(XHdcp1x_Rx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer up */ + case EVENT_PHYUP: + *NextStatePtr = STATE_UNAUTHENTICATED; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function enters a hdcp receiver state +* +* @param InstancePtr the receiver instance +* @param State the state to enter +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void EnterState(XHdcp1x_Rx *InstancePtr, tState State, + tState *NextStatePtr) +{ + /* Which state? */ + switch (State) { + + /* For the disabled state */ + case STATE_DISABLED: + Disable(InstancePtr); + break; + /* For the unauthenticated state */ + case STATE_UNAUTHENTICATED: + InstancePtr->Flags |= FLAG_PHY_UP; + break; + /* For the computations state */ + case STATE_COMPUTATIONS: + StartComputations(InstancePtr, NextStatePtr); + break; + /* For the authenticated state */ + case STATE_AUTHENTICATED: + DebugLog(InstancePtr, "authenticated"); + SetCheckLinkState(InstancePtr, TRUE); + break; + /* For the link integrity failed state */ + case STATE_LINKINTEGRITYFAILED: + InstancePtr->Stats.LinkFailures++; + ReportLinkIntegrityFailure(InstancePtr, NextStatePtr); + break; + /* For physical layer down */ + case STATE_PHYDOWN: + InstancePtr->Flags &= ~FLAG_PHY_UP; + XHdcp1x_CipherDisable(&(InstancePtr->Cipher)); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function exits a hdcp receiver state +* +* @param InstancePtr the receiver instance +* @param State the state to exit +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ExitState(XHdcp1x_Rx *InstancePtr, tState State) +{ + /* Which state? */ + switch (State) { + + /* For the disabled state */ + case STATE_DISABLED: + Enable(InstancePtr); + break; + /* For the authenticated state */ + case STATE_AUTHENTICATED: + SetCheckLinkState(InstancePtr, FALSE); + break; + /* For physical layer down */ + case STATE_PHYDOWN: + XHdcp1x_CipherEnable(&(InstancePtr->Cipher)); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function drives a hdcp receiver state machine +* +* @param InstancePtr the receiver instance +* @param Event the event to process +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void DoTheState(XHdcp1x_Rx *InstancePtr, tEvent Event) +{ + tState NextState = InstancePtr->CurrentState; + + /* Which state? */ + switch (InstancePtr->CurrentState) { + + /* For the disabled state */ + case STATE_DISABLED: + RunDisabledState(InstancePtr, Event, &NextState); + break; + /* For the unauthenticated state */ + case STATE_UNAUTHENTICATED: + RunUnauthenticatedState(InstancePtr, Event, &NextState); + break; + /* For the computations state */ + case STATE_COMPUTATIONS: + RunComputationsState(InstancePtr, Event, &NextState); + break; + /* For the authenticated state */ + case STATE_AUTHENTICATED: + RunAuthenticatedState(InstancePtr, Event, &NextState); + break; + /* For the link integrity failed state */ + case STATE_LINKINTEGRITYFAILED: + RunLinkIntegrityFailedState(InstancePtr, Event, &NextState); + break; + /* For the physical layer down state */ + case STATE_PHYDOWN: + RunPhysicalLayerDownState(InstancePtr, Event, &NextState); + break; + /* Otherwise */ + default: + break; + } + + /* Check for state change */ + while (InstancePtr->CurrentState != NextState) { + + /* Perform the state transition */ + ExitState(InstancePtr, InstancePtr->CurrentState); + InstancePtr->PreviousState = InstancePtr->CurrentState; + InstancePtr->CurrentState = NextState; + EnterState(InstancePtr, InstancePtr->CurrentState, &NextState); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function initializes a hdcp receiver state machine +* +* @param InstancePtr the receiver instance +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Init(XHdcp1x_Rx *InstancePtr) +{ + tState DummyState = STATE_DISABLED; + + /* Update theHandler */ + InstancePtr->PendingEvents = 0; + + /* Kick the state machine */ + EnterState(InstancePtr, STATE_DISABLED, &DummyState); + + return; +} + +/*****************************************************************************/ +/** +* +* This function processes the events pending on a state machine +* +* @param InstancePtr the receiver instance +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ProcessPending(XHdcp1x_Rx *InstancePtr) +{ + /* Check for any pending events */ + if (InstancePtr->PendingEvents != 0) { + u16 Pending = InstancePtr->PendingEvents; + tEvent Event = EVENT_NULL; + + /* Update InstancePtr */ + InstancePtr->PendingEvents = 0; + + /* Iterate through thePending */ + do { + /* Check for a pending event */ + if ((Pending & 1u) != 0) { + DoTheState(InstancePtr, Event); + } + + /* Update for loop */ + Pending >>= 1; + Event++; + } + while (Pending != 0); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function initializes the hdcp receiver module +* +* @param InstancePtr the receiver instance +* @param CfgPtr the configuration of the instance +* @param PhyIfPtr pointer to the underlying physical interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxCfgInitialize(XHdcp1x_Rx *InstancePtr, + const XHdcp1x_Config *CfgPtr, void* PhyIfPtr) +{ + XHdcp1x_Cipher *CipherPtr = NULL; + XHdcp1x_Port *PortPtr = NULL; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + Xil_AssertNonvoid(PhyIfPtr != NULL); + + /* Initialize InstancePtr */ + memset(InstancePtr, 0, sizeof(XHdcp1x_Rx)); + InstancePtr->CfgPtr = CfgPtr; + + /* Initialize cipher, port and state machine */ + CipherPtr = &InstancePtr->Cipher; + PortPtr = &InstancePtr->Port; + Status = XHdcp1x_PortCfgInitialize(PortPtr, CfgPtr, PhyIfPtr); + if (Status == XST_SUCCESS) { + Status = XHdcp1x_CipherCfgInitialize(CipherPtr, CfgPtr); + if (Status == XST_SUCCESS) { + Init(InstancePtr); + } + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function polls the hdcp receiver module +* +* @param InstancePtr the receiver instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* + ******************************************************************************/ +int XHdcp1x_RxPoll(XHdcp1x_Rx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Process any pending events */ + ProcessPending(InstancePtr); + + /* Poll it */ + DoTheState(InstancePtr, EVENT_POLL); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function resets an hdcp interface +* +* @param InstancePtr the transmitter instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* This function disables and then re-enables the interface. +* + ******************************************************************************/ +int XHdcp1x_RxReset(XHdcp1x_Rx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Reset it */ + PostEvent(InstancePtr, EVENT_DISABLE); + PostEvent(InstancePtr, EVENT_ENABLE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function enables a hdcp receive interface +* +* @param InstancePtr the receiver instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxEnable(XHdcp1x_Rx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Post it */ + PostEvent(InstancePtr, EVENT_ENABLE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables a hdcp receive interface +* +* @param InstancePtr the receiver instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxDisable(XHdcp1x_Rx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Post it */ + PostEvent(InstancePtr, EVENT_DISABLE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function updates the physical state of an hdcp interface +* +* @param InstancePtr the receiver instance +* @param IsUp truth value indicating the status of physical interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxSetPhysicalState(XHdcp1x_Rx *InstancePtr, int IsUp) +{ + int Status = XST_SUCCESS; + tEvent Event = EVENT_PHYDOWN; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Event */ + if (IsUp) { + Event = EVENT_PHYUP; + } + + /* Post it */ + PostEvent(InstancePtr, Event); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function set the lane count of an hdcp interface +* +* @param InstancePtr the receiver instance +* @param LaneCount the number of lanes of the interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxSetLaneCount(XHdcp1x_Rx *InstancePtr, int LaneCount) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(LaneCount > 0); + + /* Set it */ + return (XHdcp1x_CipherSetNumLanes(&(InstancePtr->Cipher), LaneCount)); +} + +/*****************************************************************************/ +/** +* +* This function initiates authentication on an interface +* +* @param InstancePtr the receiver instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxAuthenticate(XHdcp1x_Rx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Post the re-authentication request */ + PostEvent(InstancePtr, EVENT_AUTHENTICATE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function queries an interface to check if its been authenticated +* +* @param InstancePtr the receiver instance +* +* @return +* Truth value indicating authenticated (true) or not (false) +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxIsAuthenticated(const XHdcp1x_Rx *InstancePtr) +{ + int IsAuthenticated = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine IsAuthenticated */ + if (InstancePtr->CurrentState == STATE_AUTHENTICATED) { + IsAuthenticated = TRUE; + } + + return (IsAuthenticated); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the current encryption stream map +* +* @param InstancePtr the receiver instance +* +* @return +* The current encryption stream map +* +* @note +* None. +* +******************************************************************************/ +u64 XHdcp1x_RxGetEncryption(const XHdcp1x_Rx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Get it */ + return (XHdcp1x_CipherGetEncryption(&(InstancePtr->Cipher))); +} + +/*****************************************************************************/ +/** +* +* This function converts from a state to a display string +* +* @param State the state to convert +* +* @return +* The corresponding display string +* +* @note +* None. +* +******************************************************************************/ +static const char* StateToString(tState State) +{ + const char* String = NULL; + + /* Which state? */ + switch (State) { + + case STATE_DISABLED: + String = "disabled"; + break; + case STATE_UNAUTHENTICATED: + String = "unauthenticated"; + break; + case STATE_COMPUTATIONS: + String = "computations"; + break; + case STATE_AUTHENTICATED: + String = "authenticated"; + break; + case STATE_LINKINTEGRITYFAILED: + String = "link-integrity-failed"; + break; + case STATE_PHYDOWN: + String = "physical-layer-down"; + break; + default: + String = "???"; + break; + } + + return (String); +} + +/*****************************************************************************/ +/** +* +* This function implements the debug display output for receiver instances +* +* @param InstancePtr the receiver instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_RxInfo(const XHdcp1x_Rx *InstancePtr) +{ + u32 Version = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Display it */ + XHDCP1X_DEBUG_PRINTF("Type: "); + if (IsHDMI(InstancePtr)) { + XHDCP1X_DEBUG_PRINTF("hdmi-rx\r\n"); + } + else { + XHDCP1X_DEBUG_PRINTF("dp-rx\r\n"); + } + XHDCP1X_DEBUG_PRINTF("Current State: %s\r\n", + StateToString(InstancePtr->CurrentState)); + XHDCP1X_DEBUG_PRINTF("Previous State: %s\r\n", + StateToString(InstancePtr->PreviousState)); + XHDCP1X_DEBUG_PRINTF("Flags: %04X\r\n", + InstancePtr->Flags); + Version = XHdcp1x_GetDriverVersion(); + XHDCP1X_DEBUG_PRINTF("Driver Version: %d.%02d.%02d\r\n", + ((Version >> 16) &0xFFFFu), ((Version >> 8) & 0xFFu), + (Version & 0xFFu)); + Version = XHdcp1x_CipherGetVersion(&(InstancePtr->Cipher)); + XHDCP1X_DEBUG_PRINTF("Cipher Version: %d.%02d.%02d\r\n", + ((Version >> 16) &0xFFFFu), ((Version >> 8) & 0xFFu), + (Version & 0xFFu)); + XHDCP1X_DEBUG_PRINTF("\r\n"); + XHDCP1X_DEBUG_PRINTF("Rx Stats\r\n"); + XHDCP1X_DEBUG_PRINTF("Auth Attempts: %d\r\n", + InstancePtr->Stats.AuthAttempts); + XHDCP1X_DEBUG_PRINTF("Link Failures: %d\r\n", + InstancePtr->Stats.LinkFailures); + XHDCP1X_DEBUG_PRINTF("Ri Updates: %d\r\n", + InstancePtr->Stats.RiUpdates); + + XHDCP1X_DEBUG_PRINTF("\r\n"); + XHDCP1X_DEBUG_PRINTF("Cipher Stats\r\n"); + XHDCP1X_DEBUG_PRINTF("Int Count: %d\r\n", + InstancePtr->Cipher.Stats.IntCount); + + XHDCP1X_DEBUG_PRINTF("\r\n"); + XHDCP1X_DEBUG_PRINTF("Port Stats\r\n"); + XHDCP1X_DEBUG_PRINTF("Int Count: %d\r\n", + InstancePtr->Port.Stats.IntCount); + + return (XST_SUCCESS); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_rx.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_rx.h new file mode 100644 index 00000000..5dc9da20 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_rx.h @@ -0,0 +1,92 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_rx.h +* +* This file provides the interface of the HDCP RX state machine +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ +#ifndef XHDCP1X_RX_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_RX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xparameters.h" +#include "xstatus.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +int XHdcp1x_RxCfgInitialize(XHdcp1x_Rx *InstancePtr, + const XHdcp1x_Config *CfgPtr, void* PhyIfPtr); + +int XHdcp1x_RxPoll(XHdcp1x_Rx *InstancePtr); + +int XHdcp1x_RxReset(XHdcp1x_Rx *InstancePtr); +int XHdcp1x_RxEnable(XHdcp1x_Rx *InstancePtr); +int XHdcp1x_RxDisable(XHdcp1x_Rx *InstancePtr); + +int XHdcp1x_RxSetPhysicalState(XHdcp1x_Rx *InstancePtr, int IsUp); +int XHdcp1x_RxSetLaneCount(XHdcp1x_Rx *InstancePtr, int LaneCount); + +int XHdcp1x_RxAuthenticate(XHdcp1x_Rx *InstancePtr); +int XHdcp1x_RxIsAuthenticated(const XHdcp1x_Rx *InstancePtr); + +u64 XHdcp1x_RxGetEncryption(const XHdcp1x_Rx *InstancePtr); + +int XHdcp1x_RxInfo(const XHdcp1x_Rx *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* XHDCP1X_RX_H */ diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_selftest.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_selftest.c new file mode 100644 index 00000000..82b12a72 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_selftest.c @@ -0,0 +1,103 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ + +/*****************************************************************************/ +/** +* +* @file xhdcp1x_selftest.c +* +* This file contains self test function for the hdcp interface +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include +#include +#include "xhdcp1x.h" +#include "xhdcp1x_cipher.h" +#include "xhdcp1x_debug.h" +#include "xhdcp1x_port.h" +#include "xil_types.h" +#include "xparameters.h" +#include "xstatus.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Extern Declarations ******************************/ + +/************************** Global Declarations ******************************/ + +/*****************************************************************************/ +/** +* +* This function self tests an hdcp interface +* +* @param InstancePtr the interface to test +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_SelfTest(XHdcp1x *InstancePtr) +{ + int Status = XST_SUCCESS; + XHdcp1x_Cipher *CipherPtr = NULL; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine CipherPtr */ + CipherPtr = &(InstancePtr->Common.Cipher); + + /* Self test the cipher */ + if (XHdcp1x_CipherSelfTest(CipherPtr) != XST_SUCCESS) { + Status = XST_FAILURE; + } + + return (Status); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_sinit.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_sinit.c new file mode 100644 index 00000000..ba1f8a6c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_sinit.c @@ -0,0 +1,132 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_sinit.c +* +* This file contains static initialization method for Xilinx HDCP driver +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xhdcp1x_cipher.h" +#include "xparameters.h" + +/************************** Constant Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/**************************** Type Definitions *******************************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XHdcp1x_Config XHdcp1x_ConfigTable[]; + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function returns a reference to an XHdcp1x_Config structure based on +* specified device ID. +* +* @param DeviceID the unique core ID of the HDCP interface +* +* @return +* A reference to the config record in the configuration table (in xhdcp_g.c) +* corresponding the specified DeviceID. NULL if no match is found. +* +* @note +* None. +* +******************************************************************************/ +XHdcp1x_Config *XHdcp1x_LookupConfig(u16 DeviceID) +{ + /* Locals */ + XHdcp1x_Config *OneToCheck = XHdcp1x_ConfigTable; + XHdcp1x_Config *CfgPtr = NULL; + u32 NumLeft = XPAR_XHDCP_NUM_INSTANCES; + + /* Iterate through the configuration table */ + do { + /* Is this the one? */ + if (OneToCheck->DeviceId == DeviceID) + CfgPtr = OneToCheck; + + /* Update for loop */ + OneToCheck++; + NumLeft--; + + } while ((NumLeft > 0) && (CfgPtr == NULL)); + + /* Sanity Check */ + if (CfgPtr != 0) { + + u32 Value = 0; + u32 BaseAddress = CfgPtr->BaseAddress; + + /* Initialize flags */ + CfgPtr->IsRx = FALSE; + CfgPtr->IsHDMI = FALSE; + + /* Update IsRx */ + Value = (XHdcp1x_CipherReadReg(BaseAddress, + XHDCP1X_CIPHER_REG_TYPE)); + Value &= XHDCP1X_CIPHER_BITMASK_TYPE_DIRECTION; + if (Value == XHDCP1X_CIPHER_VALUE_TYPE_DIRECTION_RX) { + CfgPtr->IsRx = TRUE; + } + + /* Update IsHDMI */ + Value = (XHdcp1x_CipherReadReg(BaseAddress, + XHDCP1X_CIPHER_REG_TYPE)); + Value &= XHDCP1X_CIPHER_BITMASK_TYPE_PROTOCOL; + if (Value == XHDCP1X_CIPHER_VALUE_TYPE_PROTOCOL_HDMI) { + CfgPtr->IsHDMI = TRUE; + } + } + + /* Return */ + return (CfgPtr); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_tx.c b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_tx.c new file mode 100644 index 00000000..0fa80e59 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_tx.c @@ -0,0 +1,2717 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_tx.c +* +* This contains the main implementation file for the Xilinx HDCP transmit +* state machine +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 1.01         07/23/15 Additional documentation and formating
+* 
+* +*****************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" + +#include "sha1.h" +#include +#include +#include +#include "xhdcp1x.h" +#include "xhdcp1x_cipher.h" +#include "xhdcp1x_debug.h" +#include "xhdcp1x_platform.h" +#include "xhdcp1x_port.h" +#if defined(XPAR_XHDMI_TX_NUM_INSTANCES) && (XPAR_XHDMI_TX_NUM_INSTANCES > 0) + #include "xhdcp1x_port_hdmi.h" +#else + #include "xhdcp1x_port_dp.h" +#endif +#include "xhdcp1x_tx.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ +#define FLAG_PHY_UP (1u << 0) /**< Flag to track physical state */ +#define FLAG_IS_REPEATER (1u << 1) /**< Flag to track repeater state */ + +#define TMO_5MS ( 5u) /**< Timeout value for 5ms */ +#define TMO_100MS ( 100u) /**< Timeout value for 100ms */ +#define TMO_1SECOND (1000u) /**< Timeout value for 1s */ + +/**************************** Type Definitions *******************************/ +typedef enum +{ + EVENT_NULL, + EVENT_AUTHENTICATE, + EVENT_CHECK, + EVENT_DISABLE, + EVENT_ENABLE, + EVENT_LINKDOWN, + EVENT_PHYDOWN, + EVENT_PHYUP, + EVENT_POLL, + EVENT_TIMEOUT, + +} tEvent; + +typedef enum +{ + STATE_DISABLED, + STATE_DETERMINERXCAPABLE, + STATE_EXCHANGEKSVS, + STATE_COMPUTATIONS, + STATE_VALIDATERX, + STATE_AUTHENTICATED, + STATE_LINKINTEGRITYCHECK, + STATE_TESTFORREPEATER, + STATE_WAITFORREADY, + STATE_READKSVLIST, + STATE_UNAUTHENTICATED, + STATE_PHYDOWN, + +} tState; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is Display Port (DP) +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating DP (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsDP(InstancePtr) (!InstancePtr->CfgPtr->IsHDMI) + +/*****************************************************************************/ +/** +* +* This queries an interface to determine if it is HDMI +* +* @param InstancePtr the instance to query +* +* @return +* Truth value indicating HDMI (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +#define IsHDMI(InstancePtr) (InstancePtr->CfgPtr->IsHDMI) + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function logs a debug message on behalf of a handler state machine +* +* @param InstancePtr the receiver instance +* @param LogMsg the message to log +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void DebugLog(const XHdcp1x_Tx *InstancePtr, const char *LogMsg) +{ + char Label[16]; + + /* Format Label */ + snprintf(Label, 16, "hdcp-tx(%d) - ", InstancePtr->CfgPtr->DeviceId); + + /* Log it */ + XHDCP1X_DEBUG_LOGMSG(Label); + XHDCP1X_DEBUG_LOGMSG(LogMsg); + XHDCP1X_DEBUG_LOGMSG("\r\n"); + + return; +} + +/*****************************************************************************/ +/** +* +* This function posts an event to a state machine +* +* @param InstancePtr the receiver instance +* @param Event the event to post +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void PostEvent(XHdcp1x_Tx *InstancePtr, tEvent Event) +{ + /* Check for disable and clear any pending enable */ + if (Event == EVENT_DISABLE) { + InstancePtr->PendingEvents &= ~(1u << EVENT_ENABLE); + } + /* Check for phy-down and clear any pending phy-up */ + else if (Event == EVENT_PHYDOWN) { + InstancePtr->PendingEvents &= ~(1u << EVENT_PHYUP); + } + + /* Post it */ + InstancePtr->PendingEvents |= (1u << Event); + + return; +} + +/*****************************************************************************/ +/** +* +* This function starts a state machine's timer +* +* @param InstancePtr the state machine +* @param TimeoutInMs the timeout in milli-seconds +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void StartTimer(XHdcp1x_Tx* InstancePtr, u16 TimeoutInMs) +{ + /* Start it */ + XHdcp1x_PlatformTimerStart((XHdcp1x*) InstancePtr, TimeoutInMs); + + return; +} + +/*****************************************************************************/ +/** +* +* This function stops a state machine's timer +* +* @param InstancePtr the state machine +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void StopTimer(XHdcp1x_Tx* InstancePtr) +{ + /* Stop it */ + XHdcp1x_PlatformTimerStop((XHdcp1x*) InstancePtr); + + return; +} + +/*****************************************************************************/ +/** +* +* This function busy delays a state machine +* +* @param InstancePtr the state machine +* @param TimeoutInMs the delay time in milli-seconds +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void BusyDelay(XHdcp1x_Tx* InstancePtr, u16 DelayInMs) +{ + /* Busy wait */ + XHdcp1x_PlatformTimerBusy((XHdcp1x*) InstancePtr, DelayInMs); + + return; +} + +/*****************************************************************************/ +/** +* +* This function acts as the reauthentication callback for a state machine +* +* @param Parameter the parameter specified during registration +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ReauthenticateCallback(void* Parameter) +{ + /* Locals */ + XHdcp1x_Tx* InstancePtr = Parameter; + + /* Update statistics */ + InstancePtr->Stats.ReauthRequested++; + + /* Post the re-authentication request */ + PostEvent(InstancePtr, EVENT_AUTHENTICATE); + + return; +} + +/*****************************************************************************/ +/** +* +* This function acts as the check link callback for a state machine +* +* @param Parameter the parameter specified during registration +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void CheckLinkCallback(void* Parameter) +{ + /* Locals */ + XHdcp1x_Tx* InstancePtr = Parameter; + + /* Post the check request */ + PostEvent(InstancePtr, EVENT_CHECK); + + return; +} + +/*****************************************************************************/ +/** +* +* This function sets the check link state of the handler +* +* @param InstancePtr the hdcp state machine +* @param isEnabled truth value indicating on/off +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void SetCheckLinkState(XHdcp1x_Tx* InstancePtr, int isEnabled) +{ + /* Check for HDMI */ + if (IsHDMI(InstancePtr)) + { + XHdcp1x_Cipher *CipherPtr = &(InstancePtr->Cipher); + + /* Check for enabled */ + if (isEnabled) + { + /* Register Callback */ + XHdcp1x_CipherSetCallback(CipherPtr, + XHDCP1X_CIPHER_HANDLER_Ri_UPDATE, + &CheckLinkCallback, InstancePtr); + + /* Enable it */ + XHdcp1x_CipherSetRiUpdate(CipherPtr, TRUE); + } + /* Otherwise */ + else + { + /* Disable it */ + XHdcp1x_CipherSetRiUpdate(CipherPtr, FALSE); + } + } + + /* Return */ + return; +} + +/*****************************************************************************/ +/** +* +* This function enables encryption for a state machine +* +* @param InstancePtr the hdcp state machine +* +* @return +* void +* +* @note +* This function inserts a 5ms delay for things to settle when encryption +* is actually being disabled +* +******************************************************************************/ +static void EnableEncryption(XHdcp1x_Tx* InstancePtr) +{ + /* Check for encryption enabled */ + if (InstancePtr->EncryptionMap != 0) { + + u64 StreamMap = 0; + + /* Determine StreamMap */ + StreamMap = XHdcp1x_CipherGetEncryption(&InstancePtr->Cipher); + + /* Check if there is something to do */ + if (StreamMap != InstancePtr->EncryptionMap) { + + /* Wait a bit */ + BusyDelay(InstancePtr, TMO_5MS); + + /* Enable it */ + XHdcp1x_CipherEnableEncryption(&InstancePtr->Cipher, + InstancePtr->EncryptionMap); + } + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function disables encryption for a state machine +* +* @param InstancePtr the hdcp state machine +* +* @return +* void +* +* @note +* This function inserts a 5ms delay for things to settle when encryption +* is actually being disabled +* +******************************************************************************/ +static void DisableEncryption(XHdcp1x_Tx* InstancePtr) +{ + /* Locals */ + u64 StreamMap = XHdcp1x_CipherGetEncryption(&InstancePtr->Cipher); + + /* Check if encryption actually enabled */ + if (StreamMap != 0) { + + /* Update StreamMap for all stream */ + StreamMap = (u64) (-1); + + /* Disable it all */ + XHdcp1x_CipherDisableEncryption(&InstancePtr->Cipher, + StreamMap); + + /* Wait at least a frame */ + BusyDelay(InstancePtr, TMO_5MS); + } + + /* Return */ + return; +} + +/*****************************************************************************/ +/** +* +* This function enables a state machine +* +* @param InstancePtr the hdcp state machine +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Enable(XHdcp1x_Tx *InstancePtr) +{ + /* Clear statistics */ + memset(&(InstancePtr->Stats), 0, sizeof(InstancePtr->Stats)); + + /* Enable the crypto engine */ + XHdcp1x_CipherEnable(&InstancePtr->Cipher); + + /* Register the re-authentication callback */ + XHdcp1x_PortSetCallback(&InstancePtr->Port, + XHDCP1X_PORT_HANDLER_AUTHENTICATE, + &ReauthenticateCallback, InstancePtr); + + /* Enable the hdcp port */ + XHdcp1x_PortEnable(&InstancePtr->Port); + + return; +} + +/*****************************************************************************/ +/** +* +* This function disables a state machine +* +* @param InstancePtr the hdcp state machine +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Disable(XHdcp1x_Tx* InstancePtr) +{ + /* Disable the hdcp port */ + XHdcp1x_PortDisable(&InstancePtr->Port); + + /* Disable the cryto engine */ + XHdcp1x_CipherDisable(&InstancePtr->Cipher); + + /* Disable the timer */ + StopTimer(InstancePtr); + + /* Update InstancePtr */ + InstancePtr->Flags &= ~FLAG_IS_REPEATER; + InstancePtr->StateHelper = 0; + InstancePtr->EncryptionMap = 0; + + /* Return */ + return; +} + +/*****************************************************************************/ +/** +* +* This function checks to ensure that the remote end is hdcp capable +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void CheckRxCapable(const XHdcp1x_Tx* InstancePtr, tState *NextStatePtr) +{ + /* Check for capable */ + if (XHdcp1x_PortIsCapable(&InstancePtr->Port)) { + + /* Log */ + DebugLog(InstancePtr, "rx hdcp capable"); + + /* Update NextStatePtr */ + *NextStatePtr = STATE_EXCHANGEKSVS; + } + else { + + /* Log */ + DebugLog(InstancePtr, "rx not capable"); + + /* Update NextStatePtr */ + *NextStatePtr = STATE_UNAUTHENTICATED; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function generates the An from a random number generator +* +* @param InstancePtr the hdcp state machine +* +* @return +* A 64-bit psuedo random number (An) +* +* @note +* None. +* +******************************************************************************/ +static u64 GenerateAn(XHdcp1x_Tx* InstancePtr) +{ + XHdcp1x_Cipher *CipherPtr = &InstancePtr->Cipher; + u64 An = 0; + + /* Attempt to generate An */ + if (XHdcp1x_CipherDoRequest(CipherPtr, XHDCP1X_CIPHER_REQUEST_RNG) == + XST_SUCCESS) { + + /* Wait until done */ + while (!XHdcp1x_CipherIsRequestComplete(CipherPtr)); + + /* Update theAn */ + An = XHdcp1x_CipherGetMi(CipherPtr); + } + + /* Check if zero */ + if (An == 0) { + An = 0x351F7175406A74Dull; + } + + return (An); +} + +/*****************************************************************************/ +/** +* +* This function validates a KSV value as having 20 1s and 20 0s +* +* @param Ksv the value to validate +* +* @return +* Truth value indicating valid (TRUE) or not (FALSE) +* +* @note +* None. +* +******************************************************************************/ +static int IsKsvValid(u64 Ksv) +{ + int IsValid = FALSE; + int NumOnes = 0; + + /* Determine NumOnes */ + while (Ksv != 0) { + if ((Ksv & 1) != 0) + NumOnes++; + Ksv >>= 1; + } + + /* Check for 20 1s */ + if (NumOnes == 20) + IsValid = TRUE; + + return (IsValid); +} + +/*****************************************************************************/ +/** +* +* This function exchanges the ksvs between the two ends of the link +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ExchangeKsvs(XHdcp1x_Tx* InstancePtr, tState* NextStatePtr) +{ + /* Locals */ + XHdcp1x_Port *PortPtr = &InstancePtr->Port; + XHdcp1x_Cipher *CipherPtr = &InstancePtr->Cipher; + u8 Buf[8]; + + /* Initialize Buf */ + memset(Buf, 0, 8); + + /* Update NextStatePtr - assume failure */ + *NextStatePtr = STATE_UNAUTHENTICATED; + + /* Read the Bksv from remote end */ + if (XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_BKSV, Buf, 5) > 0) + { + u64 RemoteKsv = 0; + + /* Determine theRemoteKsv */ + XHDCP1X_PORT_BUF_TO_UINT(RemoteKsv, Buf, + XHDCP1X_PORT_SIZE_BKSV*8); + + /* Check for invalid */ + if (!IsKsvValid(RemoteKsv)) { + DebugLog(InstancePtr, "Bksv invalid"); + } + /* Check for revoked */ + else if (XHdcp1x_PlatformIsKsvRevoked((XHdcp1x*) InstancePtr, + RemoteKsv)) { + DebugLog(InstancePtr, "Bksv is revoked"); + } + /* Otherwise we're good to go */ + else { + u64 LocalKsv = 0; + u64 An = 0; + + /* Check for repeater and update InstancePtr */ + if (XHdcp1x_PortIsRepeater(&InstancePtr->Port)) { + InstancePtr->Flags |= FLAG_IS_REPEATER; + } + else { + InstancePtr->Flags &= ~FLAG_IS_REPEATER; + } + + /* Generate theAn */ + An = GenerateAn(InstancePtr); + + /* Save theAn into the state helper for use later */ + InstancePtr->StateHelper = An; + + /* Determine theLocalKsv */ + LocalKsv = XHdcp1x_CipherGetLocalKsv(CipherPtr); + + /* Load the cipher with the remote ksv */ + XHdcp1x_CipherSetRemoteKsv(CipherPtr, RemoteKsv); + + /* Send An to remote */ + XHDCP1X_PORT_UINT_TO_BUF(Buf, An, + XHDCP1X_PORT_SIZE_AN*8); + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_AN, Buf, + XHDCP1X_PORT_SIZE_AN); + + /* Send AKsv to remote */ + XHDCP1X_PORT_UINT_TO_BUF(Buf, LocalKsv, + XHDCP1X_PORT_SIZE_AKSV*8); + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_AKSV, + Buf, XHDCP1X_PORT_SIZE_AKSV); + + /* Update NextStatePtr */ + *NextStatePtr = STATE_COMPUTATIONS; + } + } + /* Otherwise */ + else { + /* Update the statistics */ + InstancePtr->Stats.ReadFailures++; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function initiates the computations for a state machine +* +* @param InstancePtr the hdcp receiver state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void StartComputations(XHdcp1x_Tx* InstancePtr, tState* NextStatePtr) +{ + /* Locals */ + XHdcp1x_Cipher *CipherPtr = &InstancePtr->Cipher; + u64 Value = 0; + u32 X = 0; + u32 Y = 0; + u32 Z = 0; + + /* Log */ + DebugLog(InstancePtr, "starting computations"); + + /* Update Value with An */ + Value = InstancePtr->StateHelper; + + /* Load the cipher B registers with An */ + X = (u32) (Value & 0x0FFFFFFFul); + Value >>= 28; + Y = (u32) (Value & 0x0FFFFFFFul); + Value >>= 28; + Z = (u32) (Value & 0x000000FFul); + if ((InstancePtr->Flags & FLAG_IS_REPEATER) != 0) { + Z |= (1ul << 8); + } + XHdcp1x_CipherSetB(CipherPtr, X, Y, Z); + + /* Initiate the block cipher */ + XHdcp1x_CipherDoRequest(CipherPtr, XHDCP1X_CIPHER_REQUEST_BLOCK); + + /* Return */ + return; +} + +/*****************************************************************************/ +/** +* +* This function polls the progress of the computations for a state machine +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void PollForComputations(XHdcp1x_Tx* InstancePtr, tState* NextStatePtr) +{ + /* Check for done */ + if (XHdcp1x_CipherIsRequestComplete(&InstancePtr->Cipher)) { + DebugLog(InstancePtr, "computations complete"); + *NextStatePtr = STATE_VALIDATERX; + } + else { + DebugLog(InstancePtr, "waiting for computations"); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function validates the attached receiver +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ValidateRx(XHdcp1x_Tx* InstancePtr, tState* NextStatePtr) +{ + XHdcp1x_Port *PortPtr = &InstancePtr->Port; + XHdcp1x_Cipher *CipherPtr = &InstancePtr->Cipher; + u8 Buf[2]; + int NumTries = 3; + + /* Update NextStatePtr */ + *NextStatePtr = STATE_UNAUTHENTICATED; + + /* Attempt to read Ro */ + do { + /* Read the remote Ro' */ + if (XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_RO, + Buf, 2) > 0) { + + char LogBuf[32]; + u16 RemoteRo = 0; + u16 LocalRo = 0; + + /* Determine RemoteRo */ + XHDCP1X_PORT_BUF_TO_UINT(RemoteRo, Buf, 2*8); + + /* Determine theLLocalRoocalRo */ + LocalRo = XHdcp1x_CipherGetRo(CipherPtr); + + /* Compare the Ro values */ + if (LocalRo == RemoteRo) { + + /* Determine theLogBuf */ + snprintf(LogBuf, 32, "rx valid Ro/Ro' (%04X)", + LocalRo); + + /* Update NextStatePtr */ + *NextStatePtr = STATE_TESTFORREPEATER; + } + /* Otherwise */ + else { + /* Determine theLogBuf */ + snprintf(LogBuf, 32, "Ro/Ro' mismatch (%04X/" + "%04X)", LocalRo, RemoteRo); + + /* Update statistics if the last attempt */ + if (NumTries == 1) + InstancePtr->Stats.AuthFailed++; + } + + /* Log */ + DebugLog(InstancePtr, LogBuf); + } + /* Otherwise */ + else { + + /* Log */ + DebugLog(InstancePtr, "Ro' read failure"); + + /* Update the statistics */ + InstancePtr->Stats.ReadFailures++; + } + + /* Update for loop */ + NumTries--; + } + while ((*NextStatePtr == STATE_UNAUTHENTICATED) && (NumTries > 0)); + + return; +} + +/*****************************************************************************/ +/** +* +* This function checks the integrity of a hdcp link +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void CheckLinkIntegrity(XHdcp1x_Tx* InstancePtr, tState* NextStatePtr) +{ + XHdcp1x_Port *PortPtr = &InstancePtr->Port; + XHdcp1x_Cipher *CipherPtr = &InstancePtr->Cipher; + u8 Buf[2]; + int NumTries = 3; + + /* Update theNextState */ + *NextStatePtr = STATE_DETERMINERXCAPABLE; + + /* Iterate through the tries */ + do + { + /* Read the remote Ri' */ + if (XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_RO, + Buf, 2) > 0) { + + char LogBuf[48]; + u16 RemoteRi = 0; + u16 LocalRi = 0; + + /* Determine theRemoteRo */ + XHDCP1X_PORT_BUF_TO_UINT(RemoteRi, Buf, 16); + + /* Determine theLocalRi */ + LocalRi = XHdcp1x_CipherGetRi(CipherPtr); + + /* Compare the local and remote values */ + if (LocalRi == RemoteRi) { + *NextStatePtr = STATE_AUTHENTICATED; + snprintf(LogBuf, 48, "link check passed Ri/Ri'" + "(%04X)", LocalRi); + } + /* Check for last attempt */ + else if (NumTries == 1) { + snprintf(LogBuf, 48, "link check failed Ri/Ri'" + "(%04X/%04X)", LocalRi, + RemoteRi); + } + + /* Log */ + DebugLog(InstancePtr, LogBuf); + } + else { + DebugLog(InstancePtr, "Ri' read failure"); + InstancePtr->Stats.ReadFailures++; + } + + /* Update for loop */ + NumTries--; + } + while ((*NextStatePtr != STATE_AUTHENTICATED) && (NumTries > 0)); + + /* Check for success */ + if (*NextStatePtr == STATE_AUTHENTICATED) { + InstancePtr->Stats.LinkCheckPassed++; + } + else { + InstancePtr->Stats.LinkCheckFailed++; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function checks the remote end to see if its a repeater +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* The implementation of this function enables encryption when a repeater is +* detected downstream. The standard is ambiguous as to the handling of this +* specific case by this behaviour is required in order to pass the Unigraf +* compliance test suite. +* +******************************************************************************/ +static void TestForRepeater(XHdcp1x_Tx *InstancePtr, tState* NextStatePtr) +{ + XHdcp1x_Port *PortPtr = &InstancePtr->Port; + + /* Check for repeater */ + if (XHdcp1x_PortIsRepeater(PortPtr)) { + + u8 Buf[XHDCP1X_PORT_SIZE_AINFO]; + + /* Update InstancePtr */ + InstancePtr->Flags |= FLAG_IS_REPEATER; + + /* Clear AINFO */ + memset(Buf, 0, XHDCP1X_PORT_SIZE_AINFO); + XHdcp1x_PortWrite(PortPtr, XHDCP1X_PORT_OFFSET_AINFO, Buf, + XHDCP1X_PORT_SIZE_AINFO); + + /* Update NextStatePtr */ + *NextStatePtr = STATE_WAITFORREADY; + + /* Log */ + DebugLog(InstancePtr, "repeater detected"); + + /* Enable authentication if needed */ + EnableEncryption(InstancePtr); + } + else { + /* Update InstancePtr */ + InstancePtr->Flags &= ~FLAG_IS_REPEATER; + + /* Update NextStatePtr */ + *NextStatePtr = STATE_AUTHENTICATED; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function polls a state machine in the "wait for ready" state +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void PollForWaitForReady(XHdcp1x_Tx *InstancePtr, tState* NextStatePtr) +{ + /* Locals */ + XHdcp1x_Port *PortPtr = &InstancePtr->Port; + u16 RepeaterInfo = 0; + int Status = XST_SUCCESS; + + /* Attempt to read the repeater info */ + Status = XHdcp1x_PortGetRepeaterInfo(PortPtr, &RepeaterInfo); + if (Status == XST_SUCCESS) { + /* Check that neither cascade or device numbers exceeded */ + if ((RepeaterInfo & 0x0880u) == 0) { + /* Check for at least one attached device */ + if ((RepeaterInfo & 0x007Fu) != 0) { + /* Update InstancePtr */ + InstancePtr->StateHelper = RepeaterInfo; + + /* Update NextStatePtr */ + *NextStatePtr = STATE_READKSVLIST; + + /* Log */ + DebugLog(InstancePtr, "devices attached: " + "ksv list ready"); + } + /* Otherwise */ + else { + /* Update NextStatePtr */ + *NextStatePtr = STATE_AUTHENTICATED; + + /* Log */ + DebugLog(InstancePtr, "no attached devices"); + } + } + /* Check for cascade exceeded */ + else { + /* Update NextStatePtr */ + *NextStatePtr = STATE_UNAUTHENTICATED; + + /* Log */ + if ((RepeaterInfo & 0x0800u) != 0) { + DebugLog(InstancePtr, "max cascade exceeded"); + } + else { + DebugLog(InstancePtr, "max devices exceeded"); + } + } + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function validates the ksv list from an attached repeater +* +* @param InstancePtr the hdcp state machine +* @param RepeaterInfo the repeater information +* +* @return +* Truth value indicating valid (TRUE) or invalid (FALSE) +* +* @note +* None. +* +******************************************************************************/ +static int ValidateKsvList(XHdcp1x_Tx* InstancePtr, u16 RepeaterInfo) +{ + XHdcp1x_Port *PortPtr = &InstancePtr->Port; + XHdcp1x_Cipher *CipherPtr = &InstancePtr->Cipher; + SHA1Context Sha1Context; + u8 Buf[24]; + int NumToRead = 0; + int IsValid = FALSE; + + /* Initialize Buf */ + memset(Buf, 0, 24); + + /* Initialize Sha1Context */ + SHA1Reset(&Sha1Context); + + /* Assume success */ + IsValid = TRUE; + + /* Determine theNumToRead */ + NumToRead = ((RepeaterInfo & 0x7Fu)*5); + + /* Read the ksv list */ + do { + int NumThisTime = XHDCP1X_PORT_SIZE_KSVFIFO; + + /* Truncate if necessary */ + if (NumThisTime > NumToRead) + NumThisTime = NumToRead; + + /* Read the next chunk of the list */ + if (XHdcp1x_PortRead(PortPtr, XHDCP1X_PORT_OFFSET_KSVFIFO, + Buf, NumThisTime) > 0) { + /* Update the calculation of V */ + SHA1Input(&Sha1Context, Buf, NumThisTime); + } + else { + /* Update the statistics */ + InstancePtr->Stats.ReadFailures++; + + /* Update isValid */ + IsValid = FALSE; + } + + /* Update for loop */ + NumToRead -= NumThisTime; + } + while ((NumToRead > 0) && (IsValid)); + + /* Check for success */ + if (IsValid) { + u64 Mo = 0; + u8 Sha1Result[SHA1HashSize]; + + /* Insert RepeaterInfo into the SHA-1 transform */ + Buf[0] = (u8) (RepeaterInfo & 0xFFu); + Buf[1] = (u8) ((RepeaterInfo >> 8) & 0xFFu); + SHA1Input(&Sha1Context, Buf, 2); + + /* Insert the Mo into the SHA-1 transform */ + Mo = XHdcp1x_CipherGetMo(CipherPtr); + XHDCP1X_PORT_UINT_TO_BUF(Buf, Mo, 64); + SHA1Input(&Sha1Context, Buf, 8); + + /* Finalize the SHA-1 result and confirm success */ + if (SHA1Result(&Sha1Context, Sha1Result) == shaSuccess) { + u8 Offset = XHDCP1X_PORT_OFFSET_VH0; + const u8* Sha1Buf = Sha1Result; + int NumIterations = (SHA1HashSize >> 2); + + /* Iterate through the SHA-1 chunks */ + do { + u32 CalcValue = 0; + u32 ReadValue = 0; + + /* Determine CalcValue */ + CalcValue = *Sha1Buf++; + CalcValue <<= 8; + CalcValue |= *Sha1Buf++; + CalcValue <<= 8; + CalcValue |= *Sha1Buf++; + CalcValue <<= 8; + CalcValue |= *Sha1Buf++; + + /* Read the value from the far end */ + if (XHdcp1x_PortRead(PortPtr, Offset, Buf, + 4) > 0) { + /* Determine ReadValue */ + XHDCP1X_PORT_BUF_TO_UINT(ReadValue, + Buf, 32); + } + else { + /* Update ReadValue */ + ReadValue = 0; + + /* Update the statistics */ + InstancePtr->Stats.ReadFailures++; + } + + /* Check for mismatch */ + if (CalcValue != ReadValue) { + IsValid = FALSE; + } + + /* Update for loop */ + Offset += 4; + NumIterations--; + } + while (NumIterations > 0); + } + /* Otherwise */ + else { + IsValid = FALSE; + } + } + + /* Return */ + return (IsValid); +} + +/*****************************************************************************/ +/** +* +* This function reads the ksv list from an attached repeater +* +* @param InstancePtr the hdcp state machine +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ReadKsvList(XHdcp1x_Tx* InstancePtr, tState* NextStatePtr) +{ + int NumAttempts = 3; + int KsvListIsValid = FALSE; + u16 RepeaterInfo = 0; + + /* Determine RepeaterInfo */ + RepeaterInfo = (u16) (InstancePtr->StateHelper & 0x0FFFu); + + /* Iterate through the attempts */ + do { + /* Attempt to validate the ksv list */ + KsvListIsValid = ValidateKsvList(InstancePtr, RepeaterInfo); + + /* Update for loop */ + NumAttempts--; + } + while ((NumAttempts > 0) && (!KsvListIsValid)); + + /* Check for success */ + if (KsvListIsValid) { + /* Log */ + DebugLog(InstancePtr, "ksv list validated"); + + /* Update NextStatePtr */ + *NextStatePtr = STATE_AUTHENTICATED; + } + else { + /* Log */ + DebugLog(InstancePtr, "ksv list invalid"); + + /* Update NextStatePtr */ + *NextStatePtr = STATE_UNAUTHENTICATED; + } + + return; +} + +/*****************************************************************************/ +/** + * + * This function queries a a handler to check if its been authenticated + * + * @param InstancePtr the hdcp state machine + * + * @return + * Truth value indicating authenticated (true) or not (false) + * + * @note + * None. + * + ******************************************************************************/ +static int IsAuthenticated(const XHdcp1x_Tx* InstancePtr) +{ + /* Locals */ + int Authenticated = FALSE; + + /* Which state? */ + switch (InstancePtr->CurrentState) { + + /* For the authenticated and link integrity check states */ + case STATE_AUTHENTICATED: + case STATE_LINKINTEGRITYCHECK: + Authenticated = TRUE; + break; + /* Otherwise */ + default: + Authenticated = FALSE; + break; + } + + return (Authenticated); +} + +/*****************************************************************************/ +/** +* +* This function runs the "disabled" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunDisabledState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For enable */ + case EVENT_ENABLE: + *NextStatePtr = STATE_UNAUTHENTICATED; + if ((InstancePtr->Flags &FLAG_PHY_UP) == 0) { + *NextStatePtr = STATE_PHYDOWN; + } + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + InstancePtr->Flags &= ~FLAG_PHY_UP; + break; + /* For physical layer up */ + case EVENT_PHYUP: + InstancePtr->Flags |= FLAG_PHY_UP; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "determine rx capable" state of the transmit state +* machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunDetermineRxCapableState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "exchange ksvs" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunExchangeKsvsState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "computations" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunComputationsState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* For poll */ + case EVENT_POLL: + PollForComputations(InstancePtr, NextStatePtr); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "validate-rx" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunValidateRxState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* For timeout */ + case EVENT_TIMEOUT: + DebugLog(InstancePtr, "validate-rx timeout"); + ValidateRx(InstancePtr, NextStatePtr); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "authenticated" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunAuthenticatedState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For check */ + case EVENT_CHECK: + *NextStatePtr = STATE_LINKINTEGRITYCHECK; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "link-integrity check" state of the transmit state +* machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunLinkIntegrityCheckState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* For poll */ + case EVENT_POLL: + CheckLinkIntegrity(InstancePtr, NextStatePtr); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "test-for-repeater" state of the transmit state +* machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunTestForRepeaterState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* For poll */ + case EVENT_POLL: + TestForRepeater(InstancePtr, NextStatePtr); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "wait-for-ready" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunWaitForReadyState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* For poll */ + case EVENT_POLL: + PollForWaitForReady(InstancePtr, NextStatePtr); + break; + /* For timeout */ + case EVENT_TIMEOUT: + DebugLog(InstancePtr, "wait-for-ready timeout"); + PollForWaitForReady(InstancePtr, NextStatePtr); + if (*NextStatePtr == STATE_WAITFORREADY) + *NextStatePtr = STATE_UNAUTHENTICATED; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "read-ksv-list" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunReadKsvListState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function runs the "unauthenticated" state of the transmit state machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunUnauthenticatedState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For authenticate */ + case EVENT_AUTHENTICATE: + *NextStatePtr = STATE_DETERMINERXCAPABLE; + break; + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer down */ + case EVENT_PHYDOWN: + *NextStatePtr = STATE_PHYDOWN; + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + + +/*****************************************************************************/ +/** +* +* This function runs the "physical-layer-down" state of the transmit state +* machine +* +* @param InstancePtr the transmitter instance +* @param Event the event to process +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void RunPhysicalLayerDownState(XHdcp1x_Tx *InstancePtr, tEvent Event, + tState *NextStatePtr) +{ + /* Which event? */ + switch (Event) { + + /* For disable */ + case EVENT_DISABLE: + *NextStatePtr = STATE_DISABLED; + break; + /* For physical layer up */ + case EVENT_PHYUP: + *NextStatePtr = STATE_UNAUTHENTICATED; + if (InstancePtr->EncryptionMap != 0) { + PostEvent(InstancePtr, EVENT_AUTHENTICATE); + } + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function enters a state +* +* @param InstancePtr the hdcp state machine +* @param State the state to enter +* @param NextStatePtr the next state +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void EnterState(XHdcp1x_Tx *InstancePtr, tState State, + tState *NextStatePtr) +{ + /* Which state? */ + switch (State) { + + /* For the disabled state */ + case STATE_DISABLED: + Disable(InstancePtr); + break; + /* For determine rx capable */ + case STATE_DETERMINERXCAPABLE: + InstancePtr->Flags |= FLAG_PHY_UP; + SetCheckLinkState(InstancePtr, FALSE); + DisableEncryption(InstancePtr); + CheckRxCapable(InstancePtr, NextStatePtr); + break; + /* For the exchange ksvs state */ + case STATE_EXCHANGEKSVS: + InstancePtr->StateHelper = 0; + ExchangeKsvs(InstancePtr, NextStatePtr); + break; + /* For the computations state */ + case STATE_COMPUTATIONS: + StartComputations(InstancePtr, NextStatePtr); + break; + /* For the validate rx state */ + case STATE_VALIDATERX: + InstancePtr->StateHelper = 0; + StartTimer(InstancePtr, TMO_100MS); + break; + /* For the wait for ready state */ + case STATE_WAITFORREADY: + InstancePtr->StateHelper = 0; + StartTimer(InstancePtr, (5*TMO_1SECOND)); + break; + /* For the read ksv list state */ + case STATE_READKSVLIST: + ReadKsvList(InstancePtr, NextStatePtr); + break; + /* For the authenticated state */ + case STATE_AUTHENTICATED: + InstancePtr->StateHelper = 0; + EnableEncryption(InstancePtr); + if (InstancePtr->PreviousState != STATE_LINKINTEGRITYCHECK) { + InstancePtr->Stats.AuthPassed++; + SetCheckLinkState(InstancePtr, TRUE); + DebugLog(InstancePtr, "authenticated"); + } + break; + /* For the link integrity check state */ + case STATE_LINKINTEGRITYCHECK: + CheckLinkIntegrity(InstancePtr, NextStatePtr); + break; + /* For the unauthenticated state */ + case STATE_UNAUTHENTICATED: + InstancePtr->Flags &= ~FLAG_IS_REPEATER; + InstancePtr->Flags |= FLAG_PHY_UP; + DisableEncryption(InstancePtr); + break; + /* For physical layer down */ + case STATE_PHYDOWN: + InstancePtr->Flags &= ~FLAG_PHY_UP; + DisableEncryption(InstancePtr); + XHdcp1x_CipherDisable(&InstancePtr->Cipher); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function exits a state +* +* @param InstancePtr the hdcp state machine +* @param State the state to exit +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ExitState(XHdcp1x_Tx *InstancePtr, tState State) +{ + /* Which state? */ + switch (State) { + + /* For the disabled state */ + case STATE_DISABLED: + Enable(InstancePtr); + break; + /* For the computations state */ + case STATE_COMPUTATIONS: + InstancePtr->StateHelper = 0; + break; + /* For the validate rx state */ + case STATE_VALIDATERX: + StopTimer(InstancePtr); + break; + /* For the wait for ready state */ + case STATE_WAITFORREADY: + StopTimer(InstancePtr); + break; + /* For the read ksv list state */ + case STATE_READKSVLIST: + InstancePtr->StateHelper = 0; + break; + /* For physical layer down */ + case STATE_PHYDOWN: + XHdcp1x_CipherEnable(&InstancePtr->Cipher); + break; + /* Otherwise */ + default: + /* Do nothing */ + break; + } + + /* Return */ + return; +} + +/*****************************************************************************/ +/** +* +* This function drives a transmit state machine +* +* @param InstancePtr the hdcp state machine +* @param theEvent the event to process +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void DoTheState(XHdcp1x_Tx *InstancePtr, tEvent Event) +{ + tState NextState = InstancePtr->CurrentState; + + /* Which state? */ + switch (InstancePtr->CurrentState) { + + /* For the disabled state */ + case STATE_DISABLED: + RunDisabledState(InstancePtr, Event, &NextState); + break; + /* For determine rx capable state */ + case STATE_DETERMINERXCAPABLE: + RunDetermineRxCapableState(InstancePtr, Event, &NextState); + break; + /* For exchange ksvs state */ + case STATE_EXCHANGEKSVS: + RunExchangeKsvsState(InstancePtr, Event, &NextState); + break; + /* For the computations state */ + case STATE_COMPUTATIONS: + RunComputationsState(InstancePtr, Event, &NextState); + break; + /* For the validate rx state */ + case STATE_VALIDATERX: + RunValidateRxState(InstancePtr, Event, &NextState); + break; + /* For the authenticated state */ + case STATE_AUTHENTICATED: + RunAuthenticatedState(InstancePtr, Event, &NextState); + break; + /* For the link integrity check state */ + case STATE_LINKINTEGRITYCHECK: + RunLinkIntegrityCheckState(InstancePtr, Event, &NextState); + break; + /* For the test for repeater state */ + case STATE_TESTFORREPEATER: + RunTestForRepeaterState(InstancePtr, Event, &NextState); + break; + /* For the wait for ready state */ + case STATE_WAITFORREADY: + RunWaitForReadyState(InstancePtr, Event, &NextState); + break; + /* For the reads ksv list state */ + case STATE_READKSVLIST: + RunReadKsvListState(InstancePtr, Event, &NextState); + break; + /* For the unauthenticated state */ + case STATE_UNAUTHENTICATED: + RunUnauthenticatedState(InstancePtr, Event, &NextState); + break; + /* For the physical layer down state */ + case STATE_PHYDOWN: + RunPhysicalLayerDownState(InstancePtr, Event, &NextState); + break; + /* Otherwise */ + default: + break; + } + + /* Check for state change */ + while (InstancePtr->CurrentState != NextState) { + + /* Perform the state transition */ + ExitState(InstancePtr, InstancePtr->CurrentState); + InstancePtr->PreviousState = InstancePtr->CurrentState; + InstancePtr->CurrentState = NextState; + EnterState(InstancePtr, InstancePtr->CurrentState, &NextState); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function initializes a transmit state machine +* +* @param InstancePtr the receiver instance +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void Init(XHdcp1x_Tx *InstancePtr) +{ + tState DummyState = STATE_DISABLED; + + /* Update theHandler */ + InstancePtr->PendingEvents = 0; + + /* Kick the state machine */ + EnterState(InstancePtr, STATE_DISABLED, &DummyState); + + return; +} + +/*****************************************************************************/ +/** +* +* This function processes the events pending on a state machine +* +* @param InstancePtr the receiver instance +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +static void ProcessPending(XHdcp1x_Tx *InstancePtr) +{ + /* Check for any pending events */ + if (InstancePtr->PendingEvents != 0) { + u16 Pending = InstancePtr->PendingEvents; + tEvent Event = EVENT_NULL; + + /* Update InstancePtr */ + InstancePtr->PendingEvents = 0; + + /* Iterate through thePending */ + do { + /* Check for a pending event */ + if ((Pending & 1u) != 0) { + DoTheState(InstancePtr, Event); + } + + /* Update for loop */ + Pending >>= 1; + Event++; + } + while (Pending != 0); + } + + return; +} + +/*****************************************************************************/ +/** +* +* This function initializes an hdcp interface +* +* @param InstancePtr the transmitter instance +* @param CfgPtr the configuration of the instance +* @param PhyIfPtr pointer to the underlying physical interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_TxCfgInitialize(XHdcp1x_Tx *InstancePtr, + const XHdcp1x_Config *CfgPtr, void* PhyIfPtr) +{ + XHdcp1x_Cipher *CipherPtr = NULL; + XHdcp1x_Port *PortPtr = NULL; + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + Xil_AssertNonvoid(PhyIfPtr != NULL); + + /* Initialize InstancePtr */ + memset(InstancePtr, 0, sizeof(XHdcp1x_Tx)); + InstancePtr->CfgPtr = CfgPtr; + + /* Initialize cipher, port and state machine */ + CipherPtr = &InstancePtr->Cipher; + PortPtr = &InstancePtr->Port; + Status = XHdcp1x_PortCfgInitialize(PortPtr, CfgPtr, PhyIfPtr); + if (Status == XST_SUCCESS) { + Status = XHdcp1x_CipherCfgInitialize(CipherPtr, CfgPtr); + if (Status == XST_SUCCESS) { + Init(InstancePtr); + } + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function polls an hdcp interface +* +* @param InstancePtr the transmitter instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* + ******************************************************************************/ +int XHdcp1x_TxPoll(XHdcp1x_Tx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Process any pending events */ + ProcessPending(InstancePtr); + + /* Poll it */ + DoTheState(InstancePtr, EVENT_POLL); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function resets an hdcp interface +* +* @param InstancePtr the transmitter instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* This function disables and then re-enables the interface. +* + ******************************************************************************/ +int XHdcp1x_TxReset(XHdcp1x_Tx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Reset it */ + PostEvent(InstancePtr, EVENT_DISABLE); + PostEvent(InstancePtr, EVENT_ENABLE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function enables an hdcp interface +* +* @param InstancePtr the transmitter instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* + ******************************************************************************/ +int XHdcp1x_TxEnable(XHdcp1x_Tx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Post it */ + PostEvent(InstancePtr, EVENT_ENABLE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables an hdcp interface +* +* @param InstancePtr the transmitter instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* + ******************************************************************************/ +int XHdcp1x_TxDisable(XHdcp1x_Tx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Post it */ + PostEvent(InstancePtr, EVENT_DISABLE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function updates the physical state of an hdcp interface +* +* @param InstancePtr the transmitter instance +* @param IsUp truth value indicating the status of physical interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* + ******************************************************************************/ +int XHdcp1x_TxSetPhysicalState(XHdcp1x_Tx *InstancePtr, int IsUp) +{ + int Status = XST_SUCCESS; + tEvent Event = EVENT_PHYDOWN; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Determine Event */ + if (IsUp) { + Event = EVENT_PHYUP; + } + + /* Post it */ + PostEvent(InstancePtr, Event); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function set the lane count of an hdcp interface +* +* @param InstancePtr the transmitter instance +* @param LaneCount the number of lanes of the interface +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* + ******************************************************************************/ +int XHdcp1x_TxSetLaneCount(XHdcp1x_Tx *InstancePtr, int LaneCount) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(LaneCount > 0); + + /* Set it */ + return (XHdcp1x_CipherSetNumLanes(&(InstancePtr->Cipher), LaneCount)); +} + +/*****************************************************************************/ +/** +* +* This function initiates authentication on an interface +* +* @param InstancePtr the transmitter instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_TxAuthenticate(XHdcp1x_Tx *InstancePtr) +{ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Post the re-authentication request */ + PostEvent(InstancePtr, EVENT_AUTHENTICATE); + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function queries an interface to check if authentication is still in +* progress +* +* @param InstancePtr the transmitter instance +* +* @return +* Truth value indicating in progress (true) or not (false) +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_TxIsInProgress(const XHdcp1x_Tx *InstancePtr) +{ + int IsInProgress = FALSE; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Which state? */ + switch (InstancePtr->CurrentState) { + + /* For the "steady" states */ + case STATE_DISABLED: + case STATE_UNAUTHENTICATED: + case STATE_AUTHENTICATED: + case STATE_LINKINTEGRITYCHECK: + IsInProgress = FALSE; + break; + /* Otherwise */ + default: + IsInProgress = TRUE; + break; + } + + return (IsInProgress); +} + +/*****************************************************************************/ +/** +* +* This function queries an interface to check if its been authenticated +* +* @param InstancePtr the transmitter instance +* +* @return +* Truth value indicating authenticated (true) or not (false) +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_TxIsAuthenticated(const XHdcp1x_Tx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + return (IsAuthenticated(InstancePtr)); +} + +/*****************************************************************************/ +/** +* +* This function retrieves the current encryption stream map +* +* @param InstancePtr the transmitter instance +* +* @return +* The current encryption stream map +* +* @note +* None. +* +******************************************************************************/ +u64 XHdcp1x_TxGetEncryption(const XHdcp1x_Tx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + return (InstancePtr->EncryptionMap); +} + +/*****************************************************************************/ +/** +* +* This function enables encryption on set of streams on a hdcp interface +* +* @param InstancePtr the transmitter instance +* @param StreamMap the bit map of streams to enable encryption on +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_TxEnableEncryption(XHdcp1x_Tx *InstancePtr, u64 StreamMap) +{ + /* Locals */ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Update InstancePtr */ + InstancePtr->EncryptionMap |= StreamMap; + + /* Check for authenticated */ + if (IsAuthenticated(InstancePtr)) { + EnableEncryption(InstancePtr); + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function disables encryption on set of streams on a hdcp interface +* +* @param InstancePtr the transmitter instance +* @param StreamMap the bit map of streams to disable encryption on +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_TxDisableEncryption(XHdcp1x_Tx *InstancePtr, u64 StreamMap) +{ + /* Locals */ + int Status = XST_SUCCESS; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Disable it */ + Status = XHdcp1x_CipherDisableEncryption(&InstancePtr->Cipher, + StreamMap); + + /* Update InstancePtr */ + if (Status == XST_SUCCESS) { + InstancePtr->EncryptionMap &= ~StreamMap; + } + + return (Status); +} + +/*****************************************************************************/ +/** +* +* This function handles a timeout on an hdcp interface +* +* @param InstancePtr the transmitter instance +* +* @return +* void +* +* @note +* None. +* +******************************************************************************/ +void XHdcp1x_TxHandleTimeout(XHdcp1x_Tx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Post the timeout */ + PostEvent(InstancePtr, EVENT_TIMEOUT); + return; +} + +/*****************************************************************************/ +/** +* +* This function converts from a state to a display string +* +* @param State the state to convert +* +* @return +* The corresponding display string +* +* @note +* None. +* +******************************************************************************/ +static const char* StateToString(tState State) +{ + const char* String = NULL; + + /* Which state? */ + switch (State) { + + case STATE_DISABLED: + String = "disabled"; + break; + case STATE_DETERMINERXCAPABLE: + String = "determine-rx-capable"; + break; + case STATE_EXCHANGEKSVS: + String = "exchange-ksvs"; + break; + case STATE_COMPUTATIONS: + String = "computations"; + break; + case STATE_VALIDATERX: + String = "validate-rx"; + break; + case STATE_AUTHENTICATED: + String = "authenticated"; + break; + case STATE_LINKINTEGRITYCHECK: + String = "link-integrity-check"; + break; + case STATE_TESTFORREPEATER: + String = "test-for-repeater"; + break; + case STATE_WAITFORREADY: + String = "wait-for-ready"; + break; + case STATE_READKSVLIST: + String = "read-ksv-list"; + break; + case STATE_UNAUTHENTICATED: + String = "unauthenticated"; + break; + case STATE_PHYDOWN: + String = "physical-layer-down"; + break; + default: + String = "???"; + break; + } + + return (String); +} + +/*****************************************************************************/ +/** +* +* This function implements the debug display output for transmit instances +* +* @param InstancePtr the receiver instance +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +int XHdcp1x_TxInfo(const XHdcp1x_Tx* InstancePtr) +{ + u32 Version = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Display it */ + XHDCP1X_DEBUG_PRINTF("Type: "); + if (IsHDMI(InstancePtr)) { + XHDCP1X_DEBUG_PRINTF("hdmi-tx\r\n"); + } + else { + XHDCP1X_DEBUG_PRINTF("dp-tx\r\n"); + } + XHDCP1X_DEBUG_PRINTF("Current State: %s\r\n", + StateToString(InstancePtr->CurrentState)); + XHDCP1X_DEBUG_PRINTF("Previous State: %s\r\n", + StateToString(InstancePtr->PreviousState)); + XHDCP1X_DEBUG_PRINTF("State Helper: %016llX\r\n", + InstancePtr->StateHelper); + XHDCP1X_DEBUG_PRINTF("Flags: %04X\r\n", + InstancePtr->Flags); + XHDCP1X_DEBUG_PRINTF("Encryption Map: %016llX\r\n", + InstancePtr->EncryptionMap); + Version = XHdcp1x_GetDriverVersion(); + XHDCP1X_DEBUG_PRINTF("Driver Version: %d.%02d.%02d\r\n", + ((Version >> 16) &0xFFFFu), ((Version >> 8) & 0xFFu), + (Version & 0xFFu)); + Version = XHdcp1x_CipherGetVersion(&(InstancePtr->Cipher)); + XHDCP1X_DEBUG_PRINTF("Cipher Version: %d.%02d.%02d\r\n", + ((Version >> 16) &0xFFFFu), ((Version >> 8) & 0xFFu), + (Version & 0xFFu)); + XHDCP1X_DEBUG_PRINTF("\r\n"); + XHDCP1X_DEBUG_PRINTF("Tx Stats\r\n"); + XHDCP1X_DEBUG_PRINTF("Auth Passed: %d\r\n", + InstancePtr->Stats.AuthPassed); + XHDCP1X_DEBUG_PRINTF("Auth Failed: %d\r\n", + InstancePtr->Stats.AuthFailed); + XHDCP1X_DEBUG_PRINTF("Reauth Requests: %d\r\n", + InstancePtr->Stats.ReauthRequested); + XHDCP1X_DEBUG_PRINTF("Check Passed: %d\r\n", + InstancePtr->Stats.LinkCheckPassed); + XHDCP1X_DEBUG_PRINTF("Check Failed: %d\r\n", + InstancePtr->Stats.LinkCheckFailed); + XHDCP1X_DEBUG_PRINTF("Read Failures: %d\r\n", + InstancePtr->Stats.ReadFailures); + + XHDCP1X_DEBUG_PRINTF("\r\n"); + XHDCP1X_DEBUG_PRINTF("Cipher Stats\r\n"); + XHDCP1X_DEBUG_PRINTF("Int Count: %d\r\n", + InstancePtr->Cipher.Stats.IntCount); + + XHDCP1X_DEBUG_PRINTF("\r\n"); + XHDCP1X_DEBUG_PRINTF("Port Stats\r\n"); + XHDCP1X_DEBUG_PRINTF("Int Count: %d\r\n", + InstancePtr->Port.Stats.IntCount); + + return (XST_SUCCESS); +} diff --git a/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_tx.h b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_tx.h new file mode 100644 index 00000000..b12743ec --- /dev/null +++ b/XilinxProcessorIPLib/drivers/hdcp1x/src/xhdcp1x_tx.h @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xhdcp1x_tx.h +* +* This file provides the interface of the HDCP TX state machine +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------------
+* 1.00         07/16/15 Initial release.
+* 
+* +******************************************************************************/ +#ifndef XHDCP1X_TX_H +/**< Prevent circular inclusions by using protection macros */ +#define XHDCP1X_TX_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xhdcp1x.h" +#include "xparameters.h" +#include "xstatus.h" +#include "xil_types.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +int XHdcp1x_TxCfgInitialize(XHdcp1x_Tx *InstancePtr, + const XHdcp1x_Config *CfgPtr, void *PhyIfPtr); + +int XHdcp1x_TxPoll(XHdcp1x_Tx *InstancePtr); + +int XHdcp1x_TxReset(XHdcp1x_Tx *InstancePtr); +int XHdcp1x_TxEnable(XHdcp1x_Tx *InstancePtr); +int XHdcp1x_TxDisable(XHdcp1x_Tx *InstancePtr); + +u64 XHdcp1x_TxGetEncryption(const XHdcp1x_Tx *InstancePtr); +int XHdcp1x_TxEnableEncryption(XHdcp1x_Tx *InstancePtr, u64 StreamMap); +int XHdcp1x_TxDisableEncryption(XHdcp1x_Tx *InstancePtr, u64 StreamMap); + +int XHdcp1x_TxSetPhysicalState(XHdcp1x_Tx *InstancePtr, int IsUp); +int XHdcp1x_TxSetLaneCount(XHdcp1x_Tx *InstancePtr, int LaneCount); + +int XHdcp1x_TxAuthenticate(XHdcp1x_Tx *InstancePtr); +int XHdcp1x_TxIsInProgress(const XHdcp1x_Tx *InstancePtr); +int XHdcp1x_TxIsAuthenticated(const XHdcp1x_Tx *InstancePtr); + +void XHdcp1x_TxHandleTimeout(XHdcp1x_Tx *InstancePtr); + +int XHdcp1x_TxInfo(const XHdcp1x_Tx *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* XHDCP1X_TX_H */