blob: f40852b7e5f6a19e8298d4b267eed79eedf9f514 [file] [log] [blame]
/**
* @file
*
* Debug out functions.
*
*
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: Common Library
* @e sub-project:
* @e \$Revision:$ @e \$Date:$
*
*/
/*****************************************************************************
*
* Copyright (C) 2012 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Advanced Micro Devices, Inc. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
***************************************************************************/
/*----------------------------------------------------------------------------------------
* M O D U L E S U S E D
*----------------------------------------------------------------------------------------
*/
#include "AGESA.h"
#include "amdlib.h"
#include "amdDebugOutLib.h"
/*----------------------------------------------------------------------------------------
* D E F I N I T I O N S A N D M A C R O S
*----------------------------------------------------------------------------------------
*/
#define COM_BASE_ADDRESS 0x3f8
#define DIVISOR 115200
#define LF 0x0a
#define CR 0x0d
typedef CHAR8 *va_list;
#ifndef _INTSIZEOF
#define _INTSIZEOF(n)( (sizeof(n) + sizeof(UINTN) - 1) & ~(sizeof(UINTN) - 1) )
#endif
#ifndef va_start
#define va_start(ap, v) ( ap = (va_list)&(v) + _INTSIZEOF(v) )
#endif
#ifndef va_arg
#define va_arg(ap, t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#endif
#ifndef va_end
#define va_end(ap) ( ap = (va_list)0 )
#endif
/*----------------------------------------------------------------------------------------
* T Y P E D E F S A N D S T R U C T U R E S
*----------------------------------------------------------------------------------------
*/
typedef struct {
UINT8 Index;
CHAR8 Buffer[256];
} StringBuffer;
/*----------------------------------------------------------------------------------------
* P R O T O T Y P E S O F L O C A L F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
VOID
SendByteToBuffer (
IN OUT StringBuffer *Buffer,
IN CHAR8 Data
);
VOID
SendStringToBuffer (
OUT StringBuffer *Buffer,
IN CHAR8 *pstr
);
VOID
SendBufferToDebugOut (
IN CHAR8* Buffer
);
VOID
ItoA (
IN UINT32 Value,
IN UINTN Radix,
OUT CHAR8 *pstr
);
VOID
SendBufferToHdtOut (
IN CHAR8* Buffer
);
VOID
SendBufferToSerialOut (
IN CHAR8* Buffer
);
VOID
InitDebugOut (VOID);
VOID
InitSerialOut (VOID);
/*----------------------------------------------------------------------------------------
* E X P O R T E D F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------------------*/
/**
* Send format string to debug out
*
*
*
* @param[in] pConfig
*
*/
VOID
LibAmdTraceDebug (
IN UINT32 Level,
IN CHAR8 *Format,
IN ...
)
{
CHAR8 TemBuffer[16];
UINT8 Index;
StringBuffer Buffer;
va_list ArgList;
if (Level == 0) {
return;
}
Buffer.Index = 0;
Index = 1;
va_start (ArgList, Format);
while (Index != 0) {
if (*Format == 0) break;
if (*Format == '%') {
INT32 Radix;
Radix = 0;
if (*(Format + 1) == 'd' || *(Format + 1) == 'D') {
Radix = 10;
}
if (*(Format + 1) == 'x' || *(Format + 1) == 'X' ) {
Radix = 16;
}
if (Radix != 0) {
ItoA (va_arg (ArgList, INT32), Radix, TemBuffer);
SendStringToBuffer (&Buffer, TemBuffer);
Format += 2;
continue;
}
}
SendByteToBuffer (&Buffer, *Format);
if (*(Format) == 0x0a) SendByteToBuffer (&Buffer, 0x0d);
Format++;
}
SendBufferToDebugOut (&Buffer.Buffer[0]);
va_end (ArgList);
}
/*----------------------------------------------------------------------------------------*/
/**
* Write string to message buffer
*
*
*
* @param[in] pConfig
*
*/
VOID
SendStringToBuffer (
OUT StringBuffer *Buffer,
IN CHAR8 *pstr
)
{
while (*pstr != 0) {
SendByteToBuffer (Buffer, *pstr);
pstr++;
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Write byte to message buffer
*
*
*
* @param[in] pConfig
*
*/
VOID
SendByteToBuffer (
IN OUT StringBuffer *Buffer,
IN CHAR8 Data
)
{
if (Buffer->Index < 255) {
Buffer->Buffer[Buffer->Index] = Data;
Buffer->Buffer[++Buffer->Index] = 0;
} else {
SendBufferToDebugOut (Buffer->Buffer);
Buffer->Index = 0;
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Integer To String
*
*
*
* @param[in] pConfig
*
*/
VOID
ItoA (
IN UINT32 Value,
IN UINTN Radix,
OUT CHAR8 *pstr
)
{
CHAR8 *tsptr;
CHAR8 *rsptr;
CHAR8 ch1;
CHAR8 ch2;
UINTN Reminder;
tsptr = pstr;
rsptr = pstr;
//Create String
do {
Reminder = Value % Radix;
Value = Value / Radix;
if (Reminder < 0xa) {
*tsptr = (UINT8)Reminder + '0';
} else {
*tsptr = (UINT8)Reminder - 0xa + 'a';
}
tsptr++;
} while (Value != 0);
//Reverse String
*tsptr = 0;
tsptr--;
while (tsptr > rsptr) {
ch1 = *tsptr;
ch2 = *rsptr;
*rsptr = ch1;
*tsptr = ch2;
tsptr--;
rsptr++;
}
}
/*----------------------------------------------------------------------------------------*/
/**
* Init debug Output
*
*
*
* @param[in] pConfig
*
*/
VOID
InitDebugOut (
VOID
)
{
#ifdef SERIAL_OUT_SUPPORT
InitSerialOut ();
#endif
}
/*----------------------------------------------------------------------------------------*/
/**
* Init Serial Output
*
*
*
* @param[in] pConfig
*
*/
VOID
InitSerialOut (
VOID
)
{
UINT8 Data;
UINT16 Divisor;
Data = 0x87;
LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x3, &Data, NULL);
Divisor = 115200 / DIVISOR;
Data = (UINT8) (Divisor & 0xFF);
LibAmdIoWrite (AccessWidth8 , COM_BASE_ADDRESS + 0x00, &Data, NULL);
Data = (UINT8) (Divisor >> 8);
LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x01, &Data, NULL);
Data = 0x07;
LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x3, &Data, NULL);
}
/*----------------------------------------------------------------------------------------*/
/**
* Init HDT Output
*
*
*
* @param[in] pConfig
*
*/
/*----------------------------------------------------------------------------------------*/
/**
* Send Buffer to debug Output
*
*
*
* @param[in] pConfig
*
*/
VOID
SendBufferToDebugOut (
IN CHAR8* Buffer
)
{
#ifdef HDT_OUT_SUPPORT
SendBufferToHdtOut (Buffer);
#endif
#ifdef SERIAL_OUT_SUPPORT
SendBufferToSerialOut (Buffer);
#endif
}
#ifdef HDT_OUT_SUPPORT
/*----------------------------------------------------------------------------------------*/
/**
* Send Buffer to debug Output
*
*
*
* @param[in] pConfig
*
*/
VOID
SendBufferToHdtOut (
IN CHAR8* Buffer
)
{
UINT32 Dr0Reg;
UINT32 Dr7Reg;
UINT32 Cr4Reg;
UINT64 MsrCurrentValue;
UINT64 MsrNewValue;
// Save the CPU debug registers for restoration at the end of the routine
LibAmdMsrRead (0xC001100A, &MsrCurrentValue, NULL);
LibAmdReadCpuReg (DR0_REG, &Dr0Reg);
LibAmdReadCpuReg (DR7_REG, &Dr7Reg);
LibAmdReadCpuReg (CR4_REG, &Cr4Reg);
//Modify the registers for HDT out
LibAmdWriteCpuReg (DR0_REG, 0x8F0);
LibAmdWriteCpuReg (DR7_REG, 0x20402);
LibAmdWriteCpuReg (CR4_REG, Cr4Reg | 0x8);
MsrNewValue = MsrCurrentValue | BIT0;
LibAmdMsrWrite (0xC001100A, &MsrNewValue, NULL);
//HDT out
LibAmdIoWrite (AccessWidth32, 0x8F0, &Buffer, NULL);
// Restore the CPU debug registers
LibAmdWriteCpuReg (CR4_REG, Cr4Reg);
LibAmdWriteCpuReg (DR7_REG, Dr7Reg);
LibAmdWriteCpuReg (DR0_REG, Dr0Reg);
LibAmdMsrWrite (0xC001100A, &MsrCurrentValue, NULL);
}
#endif
/*----------------------------------------------------------------------------------------*/
/**
* Send Buffer to debug Output
*
*
*
* @param[in] pConfig
*
*/
VOID
SendBufferToSerialOut (
IN CHAR8* Buffer
)
{
UINT8 Status;
UINT32 Count;
Count = 10000;
while (*Buffer != 0) {
do {
LibAmdIoRead (AccessWidth8, COM_BASE_ADDRESS + 0x05, &Status, NULL);
if (Status == 0xff) return;
// Loop port is ready
} while ((Status & 0x20) == 0 && (--Count) != 0);
LibAmdIoWrite (AccessWidth8, COM_BASE_ADDRESS + 0x00, Buffer, NULL);
Buffer++;
}
}