git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10420 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			259 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
|   This file provides the information dump support for EHCI when in debug mode.
 | |
| 
 | |
| Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| 
 | |
| #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 ((EFI_D_INFO, "  Do_Ping"));
 | |
|   } else {
 | |
|     DEBUG ((EFI_D_INFO, "  Do_Out"));
 | |
|   }
 | |
| 
 | |
|   if (EHC_BIT_IS_SET (State, QTD_STAT_DO_CS)) {
 | |
|     DEBUG ((EFI_D_INFO, "  Do_CS"));
 | |
|   } else {
 | |
|     DEBUG ((EFI_D_INFO, "  Do_SS"));
 | |
|   }
 | |
| 
 | |
|   if (EHC_BIT_IS_SET (State, QTD_STAT_TRANS_ERR)) {
 | |
|     DEBUG ((EFI_D_INFO, "  Transfer_Error"));
 | |
|   }
 | |
| 
 | |
|   if (EHC_BIT_IS_SET (State, QTD_STAT_BABBLE_ERR)) {
 | |
|     DEBUG ((EFI_D_INFO, "  Babble_Error"));
 | |
|   }
 | |
| 
 | |
|   if (EHC_BIT_IS_SET (State, QTD_STAT_BUFF_ERR)) {
 | |
|     DEBUG ((EFI_D_INFO, "  Buffer_Error"));
 | |
|   }
 | |
| 
 | |
|   if (EHC_BIT_IS_SET (State, QTD_STAT_HALTED)) {
 | |
|     DEBUG ((EFI_D_INFO, "  Halted"));
 | |
|   }
 | |
| 
 | |
|   if (EHC_BIT_IS_SET (State, QTD_STAT_ACTIVE)) {
 | |
|     DEBUG ((EFI_D_INFO, "  Active"));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\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 ((EFI_D_INFO, Msg));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Queue TD @ 0x%p, data length %d\n", Qtd, (UINT32)Qtd->DataLen));
 | |
| 
 | |
|   QtdHw = &Qtd->QtdHw;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Next QTD     : %x\n", QtdHw->NextQtd));
 | |
|   DEBUG ((EFI_D_INFO, "AltNext QTD  : %x\n", QtdHw->AltNext));
 | |
|   DEBUG ((EFI_D_INFO, "Status       : %x\n", QtdHw->Status));
 | |
|   EhcDumpStatus (QtdHw->Status);
 | |
| 
 | |
|   if (QtdHw->Pid == QTD_PID_SETUP) {
 | |
|     DEBUG ((EFI_D_INFO, "PID          : Setup\n"));
 | |
| 
 | |
|   } else if (QtdHw->Pid == QTD_PID_INPUT) {
 | |
|     DEBUG ((EFI_D_INFO, "PID          : IN\n"));
 | |
| 
 | |
|   } else if (QtdHw->Pid == QTD_PID_OUTPUT) {
 | |
|     DEBUG ((EFI_D_INFO, "PID          : OUT\n"));
 | |
| 
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Error Count  : %d\n", QtdHw->ErrCnt));
 | |
|   DEBUG ((EFI_D_INFO, "Current Page : %d\n", QtdHw->CurPage));
 | |
|   DEBUG ((EFI_D_INFO, "IOC          : %d\n", QtdHw->Ioc));
 | |
|   DEBUG ((EFI_D_INFO, "Total Bytes  : %d\n", QtdHw->TotalBytes));
 | |
|   DEBUG ((EFI_D_INFO, "Data Toggle  : %d\n", QtdHw->DataToggle));
 | |
| 
 | |
|   for (Index = 0; Index < 5; Index++) {
 | |
|     DEBUG ((EFI_D_INFO, "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 ((EFI_D_INFO, Msg));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Queue head @ 0x%p, interval %ld, next qh %p\n",
 | |
|                                 Qh, (UINT64)Qh->Interval, Qh->NextQh));
 | |
| 
 | |
|   QhHw = &Qh->QhHw;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Hoziontal link: %x\n", QhHw->HorizonLink));
 | |
|   DEBUG ((EFI_D_INFO, "Device address: %d\n", QhHw->DeviceAddr));
 | |
|   DEBUG ((EFI_D_INFO, "Inactive      : %d\n", QhHw->Inactive));
 | |
|   DEBUG ((EFI_D_INFO, "EP number     : %d\n", QhHw->EpNum));
 | |
|   DEBUG ((EFI_D_INFO, "EP speed      : %d\n", QhHw->EpSpeed));
 | |
|   DEBUG ((EFI_D_INFO, "DT control    : %d\n", QhHw->DtCtrl));
 | |
|   DEBUG ((EFI_D_INFO, "Reclaim head  : %d\n", QhHw->ReclaimHead));
 | |
|   DEBUG ((EFI_D_INFO, "Max packet len: %d\n", QhHw->MaxPacketLen));
 | |
|   DEBUG ((EFI_D_INFO, "Ctrl EP       : %d\n", QhHw->CtrlEp));
 | |
|   DEBUG ((EFI_D_INFO, "Nak reload    : %d\n", QhHw->NakReload));
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "SMask         : %x\n", QhHw->SMask));
 | |
|   DEBUG ((EFI_D_INFO, "CMask         : %x\n", QhHw->CMask));
 | |
|   DEBUG ((EFI_D_INFO, "Hub address   : %d\n", QhHw->HubAddr));
 | |
|   DEBUG ((EFI_D_INFO, "Hub port      : %d\n", QhHw->PortNum));
 | |
|   DEBUG ((EFI_D_INFO, "Multiplier    : %d\n", QhHw->Multiplier));
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Cur QTD       : %x\n", QhHw->CurQtd));
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Next QTD      : %x\n", QhHw->NextQtd));
 | |
|   DEBUG ((EFI_D_INFO, "AltNext QTD   : %x\n", QhHw->AltQtd));
 | |
|   DEBUG ((EFI_D_INFO, "Status        : %x\n", QhHw->Status));
 | |
| 
 | |
|   EhcDumpStatus (QhHw->Status);
 | |
| 
 | |
|   if (QhHw->Pid == QTD_PID_SETUP) {
 | |
|     DEBUG ((EFI_D_INFO, "PID           : Setup\n"));
 | |
| 
 | |
|   } else if (QhHw->Pid == QTD_PID_INPUT) {
 | |
|     DEBUG ((EFI_D_INFO, "PID           : IN\n"));
 | |
| 
 | |
|   } else if (QhHw->Pid == QTD_PID_OUTPUT) {
 | |
|     DEBUG ((EFI_D_INFO, "PID           : OUT\n"));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "Error Count   : %d\n", QhHw->ErrCnt));
 | |
|   DEBUG ((EFI_D_INFO, "Current Page  : %d\n", QhHw->CurPage));
 | |
|   DEBUG ((EFI_D_INFO, "IOC           : %d\n", QhHw->Ioc));
 | |
|   DEBUG ((EFI_D_INFO, "Total Bytes   : %d\n", QhHw->TotalBytes));
 | |
|   DEBUG ((EFI_D_INFO, "Data Toggle   : %d\n", QhHw->DataToggle));
 | |
| 
 | |
|   for (Index = 0; Index < 5; Index++) {
 | |
|     DEBUG ((EFI_D_INFO, "Page[%d]       : 0x%x\n", Index, QhHw->Page[Index]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
| 
 | |
|   EFI_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 ((EFI_D_INFO,"\n"));
 | |
|     }
 | |
| 
 | |
|     DEBUG ((EFI_D_INFO, "%02x ", Buf[Index]));
 | |
|   }
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "\n"));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dump the EHCI status registers.
 | |
| 
 | |
|   @param  Ehc    USB EHCI Host Controller instance
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EhcDumpRegs (
 | |
|   IN  USB2_HC_DEV         *Ehc
 | |
|   )
 | |
| {
 | |
|   UINT8   Index;
 | |
| 
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_CAPLENGTH_OFFSET   = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_CAPLENGTH_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_HCSPARAMS_OFFSET   = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_HCSPARAMS_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_HCCPARAMS_OFFSET   = 0x%08x\n", EhcReadCapRegister (Ehc, EHC_HCCPARAMS_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_USBCMD_OFFSET      = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBCMD_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_USBSTS_OFFSET      = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBSTS_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_USBINTR_OFFSET     = 0x%08x\n", EhcReadOpReg (Ehc, EHC_USBINTR_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_FRINDEX_OFFSET     = 0x%08x\n", EhcReadOpReg (Ehc, EHC_FRINDEX_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_CTRLDSSEG_OFFSET   = 0x%08x\n", EhcReadOpReg (Ehc,  EHC_CTRLDSSEG_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_FRAME_BASE_OFFSET  = 0x%08x\n", EhcReadOpReg (Ehc,  EHC_FRAME_BASE_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_ASYNC_HEAD_OFFSET  = 0x%08x\n", EhcReadOpReg (Ehc, EHC_ASYNC_HEAD_OFFSET)));
 | |
|   DEBUG ((EFI_D_INFO, "  EHC_CONFIG_FLAG_OFFSET = 0x%08x\n", EhcReadOpReg (Ehc, EHC_CONFIG_FLAG_OFFSET)));
 | |
|   for (Index = 0; Index < (UINT8) (Ehc->HcStructParams & HCSP_NPORTS); Index++) {
 | |
|     DEBUG ((EFI_D_INFO, "  EHC_PORT_STAT_OFFSET(%d)  = 0x%08x\n", Index, EhcReadOpReg (Ehc, EHC_PORT_STAT_OFFSET + (4 * Index))));
 | |
|   }
 | |
| }
 |