/** @file
This file provides the information dump support for EHCI when in debug mode.
Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "Ehci.h"
/**
Dump the status byte in QTD/QH to a more friendly format.
@param State The state in the QTD/QH.
**/
VOID
EhcDumpStatus (
IN UINT32 State
)
{
if (EHC_BIT_IS_SET (State, QTD_STAT_DO_PING)) {
DEBUG ((DEBUG_VERBOSE, " Do_Ping"));
} else {
DEBUG ((DEBUG_VERBOSE, " Do_Out"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_DO_CS)) {
DEBUG ((DEBUG_VERBOSE, " Do_CS"));
} else {
DEBUG ((DEBUG_VERBOSE, " Do_SS"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_TRANS_ERR)) {
DEBUG ((DEBUG_VERBOSE, " Transfer_Error"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_BABBLE_ERR)) {
DEBUG ((DEBUG_VERBOSE, " Babble_Error"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_BUFF_ERR)) {
DEBUG ((DEBUG_VERBOSE, " Buffer_Error"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_HALTED)) {
DEBUG ((DEBUG_VERBOSE, " Halted"));
}
if (EHC_BIT_IS_SET (State, QTD_STAT_ACTIVE)) {
DEBUG ((DEBUG_VERBOSE, " Active"));
}
DEBUG ((DEBUG_VERBOSE, "\n"));
}
/**
Dump the fields of a QTD.
@param Qtd The QTD to dump.
@param Msg The message to print before the dump.
**/
VOID
EhcDumpQtd (
IN EHC_QTD *Qtd,
IN CHAR8 *Msg
)
{
QTD_HW *QtdHw;
UINTN Index;
if (Msg != NULL) {
DEBUG ((DEBUG_VERBOSE, Msg));
}
DEBUG ((DEBUG_VERBOSE, "Queue TD @ 0x%p, data length %d\n", Qtd, (UINT32)Qtd->DataLen));
QtdHw = &Qtd->QtdHw;
DEBUG ((DEBUG_VERBOSE, "Next QTD : %x\n", QtdHw->NextQtd));
DEBUG ((DEBUG_VERBOSE, "AltNext QTD : %x\n", QtdHw->AltNext));
DEBUG ((DEBUG_VERBOSE, "Status : %x\n", QtdHw->Status));
EhcDumpStatus (QtdHw->Status);
if (QtdHw->Pid == QTD_PID_SETUP) {
DEBUG ((DEBUG_VERBOSE, "PID : Setup\n"));
} else if (QtdHw->Pid == QTD_PID_INPUT) {
DEBUG ((DEBUG_VERBOSE, "PID : IN\n"));
} else if (QtdHw->Pid == QTD_PID_OUTPUT) {
DEBUG ((DEBUG_VERBOSE, "PID : OUT\n"));
}
DEBUG ((DEBUG_VERBOSE, "Error Count : %d\n", QtdHw->ErrCnt));
DEBUG ((DEBUG_VERBOSE, "Current Page : %d\n", QtdHw->CurPage));
DEBUG ((DEBUG_VERBOSE, "IOC : %d\n", QtdHw->Ioc));
DEBUG ((DEBUG_VERBOSE, "Total Bytes : %d\n", QtdHw->TotalBytes));
DEBUG ((DEBUG_VERBOSE, "Data Toggle : %d\n", QtdHw->DataToggle));
for (Index = 0; Index < 5; Index++) {
DEBUG ((DEBUG_VERBOSE, "Page[%d] : 0x%x\n", (UINT32)Index, QtdHw->Page[Index]));
}
}
/**
Dump the queue head.
@param Qh The queue head to dump.
@param Msg The message to print before the dump.
@param DumpBuf Whether to dump the memory buffer of the associated QTD.
**/
VOID
EhcDumpQh (
IN EHC_QH *Qh,
IN CHAR8 *Msg,
IN BOOLEAN DumpBuf
)
{
EHC_QTD *Qtd;
QH_HW *QhHw;
LIST_ENTRY *Entry;
UINTN Index;
if (Msg != NULL) {
DEBUG ((DEBUG_VERBOSE, Msg));
}
DEBUG ((
DEBUG_VERBOSE,
"Queue head @ 0x%p, interval %ld, next qh %p\n",
Qh,
(UINT64)Qh->Interval,
Qh->NextQh
));
QhHw = &Qh->QhHw;
DEBUG ((DEBUG_VERBOSE, "Hoziontal link: %x\n", QhHw->HorizonLink));
DEBUG ((DEBUG_VERBOSE, "Device address: %d\n", QhHw->DeviceAddr));
DEBUG ((DEBUG_VERBOSE, "Inactive : %d\n", QhHw->Inactive));
DEBUG ((DEBUG_VERBOSE, "EP number : %d\n", QhHw->EpNum));
DEBUG ((DEBUG_VERBOSE, "EP speed : %d\n", QhHw->EpSpeed));
DEBUG ((DEBUG_VERBOSE, "DT control : %d\n", QhHw->DtCtrl));
DEBUG ((DEBUG_VERBOSE, "Reclaim head : %d\n", QhHw->ReclaimHead));
DEBUG ((DEBUG_VERBOSE, "Max packet len: %d\n", QhHw->MaxPacketLen));
DEBUG ((DEBUG_VERBOSE, "Ctrl EP : %d\n", QhHw->CtrlEp));
DEBUG ((DEBUG_VERBOSE, "Nak reload : %d\n", QhHw->NakReload));
DEBUG ((DEBUG_VERBOSE, "SMask : %x\n", QhHw->SMask));
DEBUG ((DEBUG_VERBOSE, "CMask : %x\n", QhHw->CMask));
DEBUG ((DEBUG_VERBOSE, "Hub address : %d\n", QhHw->HubAddr));
DEBUG ((DEBUG_VERBOSE, "Hub port : %d\n", QhHw->PortNum));
DEBUG ((DEBUG_VERBOSE, "Multiplier : %d\n", QhHw->Multiplier));
DEBUG ((DEBUG_VERBOSE, "Cur QTD : %x\n", QhHw->CurQtd));
DEBUG ((DEBUG_VERBOSE, "Next QTD : %x\n", QhHw->NextQtd));
DEBUG ((DEBUG_VERBOSE, "AltNext QTD : %x\n", QhHw->AltQtd));
DEBUG ((DEBUG_VERBOSE, "Status : %x\n", QhHw->Status));
EhcDumpStatus (QhHw->Status);
if (QhHw->Pid == QTD_PID_SETUP) {
DEBUG ((DEBUG_VERBOSE, "PID : Setup\n"));
} else if (QhHw->Pid == QTD_PID_INPUT) {
DEBUG ((DEBUG_VERBOSE, "PID : IN\n"));
} else if (QhHw->Pid == QTD_PID_OUTPUT) {
DEBUG ((DEBUG_VERBOSE, "PID : OUT\n"));
}
DEBUG ((DEBUG_VERBOSE, "Error Count : %d\n", QhHw->ErrCnt));
DEBUG ((DEBUG_VERBOSE, "Current Page : %d\n", QhHw->CurPage));
DEBUG ((DEBUG_VERBOSE, "IOC : %d\n", QhHw->Ioc));
DEBUG ((DEBUG_VERBOSE, "Total Bytes : %d\n", QhHw->TotalBytes));
DEBUG ((DEBUG_VERBOSE, "Data Toggle : %d\n", QhHw->DataToggle));
for (Index = 0; Index < 5; Index++) {
DEBUG ((DEBUG_VERBOSE, "Page[%d] : 0x%x\n", Index, QhHw->Page[Index]));
}
DEBUG ((DEBUG_VERBOSE, "\n"));
BASE_LIST_FOR_EACH (Entry, &Qh->Qtds) {
Qtd = EFI_LIST_CONTAINER (Entry, EHC_QTD, QtdList);
EhcDumpQtd (Qtd, NULL);
if (DumpBuf && (Qtd->DataLen != 0)) {
EhcDumpBuf (Qtd->Data, Qtd->DataLen);
}
}
}
/**
Dump the buffer in the form of hex.
@param Buf The buffer to dump.
@param Len The length of buffer.
**/
VOID
EhcDumpBuf (
IN UINT8 *Buf,
IN UINTN Len
)
{
UINTN Index;
for (Index = 0; Index < Len; Index++) {
if (Index % 16 == 0) {
DEBUG ((DEBUG_VERBOSE, "\n"));
}
DEBUG ((DEBUG_VERBOSE, "%02x ", Buf[Index]));
}
DEBUG ((DEBUG_VERBOSE, "\n"));
}