1468 lines
37 KiB
C
1468 lines
37 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
iod.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements functions that are specific to the IOD ASIC.
|
|||
|
The IOD ASIC is a control ASIC for PCI on EV5-based Rawhide
|
|||
|
systems.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Eric Rehm 12-Apr-1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "halp.h"
|
|||
|
#include "rawhide.h"
|
|||
|
|
|||
|
BOOLEAN IodInitialized = FALSE;
|
|||
|
|
|||
|
MC_DEVICE_MASK HalpIodMask = 0x0;
|
|||
|
MC_DEVICE_MASK HalpCpuMask = 0x0;
|
|||
|
MC_DEVICE_MASK HalpGcdMask = 0x0;
|
|||
|
|
|||
|
//
|
|||
|
// Declare the IOD interrupt vector table and global pointer
|
|||
|
// Due to the fact that the MC_DEVICE_ID specifies the 64
|
|||
|
// byte offset into this global table, we must allocate
|
|||
|
// full table for all
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
PIOD_POSTED_INTERRUPT HalpIodPostedInterrupts;
|
|||
|
|
|||
|
//
|
|||
|
// Declare the PCI logical to physical mapping structure
|
|||
|
//
|
|||
|
|
|||
|
MC_DEVICE_ID HalpIodLogicalToPhysical[RAWHIDE_MAXIMUM_PCI_BUS];
|
|||
|
|
|||
|
//
|
|||
|
// The revision of the IOD. Software visible differences may exist between
|
|||
|
// passes of the IOD. The revision is determined once at the start of
|
|||
|
// run-time and used in places where the software must diverge.
|
|||
|
//
|
|||
|
|
|||
|
IOD_PCI_REVISION HalpIodRevision;
|
|||
|
|
|||
|
//
|
|||
|
// Declare routines local to this module
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpInitializeBitMap (
|
|||
|
IN PRTL_BITMAP BitMapHeader,
|
|||
|
IN PULONG BitMapBuffer,
|
|||
|
IN ULONG SizeOfBitMap
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpInitializeIodMappingTable(
|
|||
|
MC_DEVICE_ID McDeviceId,
|
|||
|
ULONG PciBusNumber,
|
|||
|
va_list Arguments
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This enumeration routine initialize the IOD logical to physical
|
|||
|
mapping table. The Logical IOD number is via a static variable
|
|||
|
that is incremented for each invokation of this routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McDeviceId - IOD device id to be mapped.
|
|||
|
|
|||
|
PciBusNumber - Logical PCI Bus number (unused).
|
|||
|
|
|||
|
Arguments - variable arguments. None for this routine.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
None:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HalpIodLogicalToPhysical[PciBusNumber].all = 0;
|
|||
|
HalpIodLogicalToPhysical[PciBusNumber].Gid = McDeviceId.Gid;
|
|||
|
HalpIodLogicalToPhysical[PciBusNumber].Mid = McDeviceId.Mid;
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
DbgPrint("HalpIodLogicalToPhysical[%d] = %x\n",
|
|||
|
PciBusNumber,
|
|||
|
HalpIodLogicalToPhysical[PciBusNumber]);
|
|||
|
#endif // HALDBG
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpInitializeIodVectorTable(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize the global pointer to the IOD vector table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Allocate the Global Iod vector table.
|
|||
|
//
|
|||
|
|
|||
|
// mdbfix - we only need 4K, but require a page aligned
|
|||
|
// address due to the fact that IOD uses target CPU's
|
|||
|
// MC_DEVICE_ID as bits <11,6> of the vector table address
|
|||
|
// in memory. So we allocate a PAGE more to guarantee
|
|||
|
// a page aligned address.
|
|||
|
//
|
|||
|
|
|||
|
HalpIodPostedInterrupts =
|
|||
|
ExAllocatePool(
|
|||
|
NonPagedPool,
|
|||
|
__4K + __8K
|
|||
|
);
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
DbgPrint("HalpIodPostedInterrupts = 0x%x\n", HalpIodPostedInterrupts);
|
|||
|
#endif
|
|||
|
|
|||
|
if (HalpIodPostedInterrupts == NULL) {
|
|||
|
|
|||
|
DbgBreakPoint();
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpInitializeIod(
|
|||
|
MC_DEVICE_ID McDeviceId,
|
|||
|
ULONG PciBusNumber,
|
|||
|
va_list Arguments
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This enumeration routine initializes the corresponding IOD.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
|
|||
|
|
|||
|
PciBusNumber - Logical PCI Bus number (unused).
|
|||
|
|
|||
|
Arguments - Variable arguments including:
|
|||
|
|
|||
|
1) LoaderBlock - Supplies a pointer to the loader parameter block.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
IOD_CAP_CONTROL IodCapControl;
|
|||
|
IOD_CAP_ERR IodCapError;
|
|||
|
IOD_WBASE Wbase;
|
|||
|
IOD_TBASE Tbase;
|
|||
|
IOD_WMASK Wmask;
|
|||
|
IOD_TBIA Tbia;
|
|||
|
IOD_MDPA_STAT IodMdpaStat;
|
|||
|
IOD_MDPB_STAT IodMdpbStat;
|
|||
|
IOD_MDPA_DIAG IodMdpaDiag;
|
|||
|
IOD_MDPB_DIAG IodMdpbDiag;
|
|||
|
PLOADER_PARAMETER_BLOCK LoaderBlock;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize parameters
|
|||
|
//
|
|||
|
|
|||
|
// mdbfix - this is not used
|
|||
|
// LoaderBlock = va_arg(Arguments, PLOADER_PARAMETER_BLOCK);
|
|||
|
|
|||
|
//
|
|||
|
// Read the IOD revision.
|
|||
|
//
|
|||
|
|
|||
|
HalpIodRevision.all =
|
|||
|
READ_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision );
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
|
|||
|
DbgPrint( "Entry - HalpInitializeIod\n\n");
|
|||
|
|
|||
|
DbgPrint( "IOD (%x,%x) Revision: \n", McDeviceId.Gid, McDeviceId.Mid);
|
|||
|
DbgPrint( "\tCAP = 0x%x\n", HalpIodRevision.CapRev );
|
|||
|
DbgPrint( "\tHorse = 0x%x\n", HalpIodRevision.HorseRev );
|
|||
|
DbgPrint( "\tSaddle = 0x%x\n", HalpIodRevision.SaddleRev );
|
|||
|
DbgPrint( "\tSaddle Type = 0x%x\n", HalpIodRevision.SaddleType );
|
|||
|
DbgPrint( "\tEISA Present = 0x%x\n", HalpIodRevision.EisaPresent );
|
|||
|
DbgPrint( "\tPCI Class, Subclass = 0x%0.2x%0.2x\n",
|
|||
|
HalpIodRevision.BaseClass, HalpIodRevision.SubClass );
|
|||
|
|
|||
|
#endif //HALDBG
|
|||
|
|
|||
|
//
|
|||
|
// Initialize IOD Control. Currently, take the initial values
|
|||
|
// set by the Extended SROM.
|
|||
|
//
|
|||
|
|
|||
|
IodCapControl.all =
|
|||
|
READ_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
|
|||
|
DbgPrint( "Read Iod CAP Control = 0x%0.4x\n", IodCapControl.all );
|
|||
|
|
|||
|
#endif //HALDBG
|
|||
|
|
|||
|
|
|||
|
#ifdef RISP //ecrfix
|
|||
|
|
|||
|
//
|
|||
|
// For RISP, initialized as per Rawhide S/W Programmers Manual
|
|||
|
//
|
|||
|
|
|||
|
IodCapControl.DlyRdEn = 1;
|
|||
|
IodCapControl.PciMemEn = 1;
|
|||
|
IodCapControl.PciReq64 = 1;
|
|||
|
IodCapControl.PciAck64 = 1;
|
|||
|
IodCapControl.PciAddrPe= 1;
|
|||
|
IodCapControl.McCmdAddrPe= 1;
|
|||
|
IodCapControl.McNxmEn = 1;
|
|||
|
IodCapControl.McBusMonEn= 1;
|
|||
|
IodCapControl.PendNum = 11; // 12 - [ (0 * 2) + 1 + (0 * 2)]
|
|||
|
IodCapControl.RdType = 2;
|
|||
|
IodCapControl.RlType = 2;
|
|||
|
IodCapControl.RmType = 2;
|
|||
|
IodCapControl.PartialWrEn = 0;
|
|||
|
IodCapControl.ArbMode = 0;
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl,
|
|||
|
IodCapControl.all );
|
|||
|
#if HALDBG
|
|||
|
|
|||
|
IodCapControl.all =
|
|||
|
READ_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl );
|
|||
|
|
|||
|
DbgPrint( "Read Iod CAP Control = 0x%0.4x\n (after sets)", IodCapControl.all );
|
|||
|
|
|||
|
#endif //HALDBG
|
|||
|
|
|||
|
#endif //RISP
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Disable all of the scatter/gather windows.
|
|||
|
//
|
|||
|
|
|||
|
Wbase.all = 0;
|
|||
|
Wbase.Wen = 0;
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base,
|
|||
|
Wbase.all );
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base,
|
|||
|
Wbase.all );
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2base,
|
|||
|
Wbase.all );
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3base,
|
|||
|
Wbase.all );
|
|||
|
|
|||
|
//
|
|||
|
// Invalidate all of the TLB Entries.
|
|||
|
//
|
|||
|
|
|||
|
Tbia.all = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Perform the invalidation.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia,
|
|||
|
Tbia.all );
|
|||
|
|
|||
|
//
|
|||
|
// Clear any pending error bits in the IOD_CAP_ERR register:
|
|||
|
//
|
|||
|
|
|||
|
IodCapError.all = 0; // Clear all bits
|
|||
|
|
|||
|
IodCapError.Perr = 1; // PCI bus perr detected
|
|||
|
IodCapError.Serr = 1; // PCI bus serr detected
|
|||
|
IodCapError.Mab = 1; // PCI bus master abort detected
|
|||
|
IodCapError.PteInv = 1; // Invalid Pte
|
|||
|
IodCapError.PioOvfl = 1; // Pio Ovfl
|
|||
|
IodCapError.LostMcErr = 1; // Lost error
|
|||
|
IodCapError.McAddrPerr = 1; // MC bus comd/addr parity error
|
|||
|
IodCapError.Nxm = 1; // MC bus Non-existent memory error
|
|||
|
IodCapError.CrdA = 1; // Correctable ECC error on MDPA
|
|||
|
IodCapError.CrdB = 1; // Correctable ECC error on MDPB
|
|||
|
IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
|
|||
|
IodCapError.RdsA = 1; // Uncorrectable ECC error on MDPA
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
|
|||
|
IodCapError.all );
|
|||
|
|
|||
|
//
|
|||
|
// Clear any ECC error syndrome bits in the IOD_MDPA/B_SYN registers:
|
|||
|
//
|
|||
|
|
|||
|
IodMdpaStat.all = 0;
|
|||
|
IodMdpaStat.Crd = 1; // Correctable ECC error (also clears Rds bit)
|
|||
|
|
|||
|
IodMdpbStat.all = 0;
|
|||
|
IodMdpbStat.Crd = 1; // Correctable ECC error (also clears Rds bit)
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat,
|
|||
|
IodMdpaStat.all );
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat,
|
|||
|
IodMdpbStat.all );
|
|||
|
|
|||
|
#if 0 // CAP/MDP Bug
|
|||
|
|
|||
|
IodMdpaStat.all =
|
|||
|
READ_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat );
|
|||
|
|
|||
|
DbgPrint( "MDPA (%x,%x) Revision = 0x%x\n",
|
|||
|
McDeviceId.Gid, McDeviceId.Mid, IodMdpaStat.MdpaRev);
|
|||
|
|
|||
|
IodMdpaStat.all =
|
|||
|
READ_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat );
|
|||
|
|
|||
|
DbgPrint( "MDPB (%x,%x) Revision = 0x%x\n",
|
|||
|
McDeviceId.Gid, McDeviceId.Mid, IodMdpbStat.MdpbRev);
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize MDP Diagnostic Checking. Currently just take the
|
|||
|
// initial values set by the Extended SROM. Do both Mdpa and Mdpb.
|
|||
|
//
|
|||
|
|
|||
|
#if 0 // CAP/MDP Bug
|
|||
|
|
|||
|
IodMdpaDiag.all =
|
|||
|
READ_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag );
|
|||
|
|
|||
|
DbgPrint( "Read Iod MDPA Diag = 0x%0.4x\n", IodMdpaDiag.all );
|
|||
|
|
|||
|
IodMdpbDiag.all =
|
|||
|
READ_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag );
|
|||
|
|
|||
|
DbgPrint( "Read Iod MDPB Diag = 0x%0.4x\n", IodMdpbDiag.all );
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
#if defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
//
|
|||
|
// Disable MCI bus interrupts
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl,
|
|||
|
(IOD_INT_CTL_DISABLE_IO_INT | IOD_INT_CTL_DISABLE_VECT_WRITE)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Clear interrupt request register (New for CAP Rev2.3)
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq,
|
|||
|
IodIntMask
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Clear all pending interrupts for this IOD
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)IOD_INT_CSRS_QVA)->IntAck0,
|
|||
|
0x0
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Clear all pending EISA interrupts for IOD 0
|
|||
|
//
|
|||
|
|
|||
|
if ( (McDeviceId.Gid == GidPrimary) && (McDeviceId.Mid == MidPci0) ) {
|
|||
|
|
|||
|
INTERRUPT_ACKNOWLEDGE((PVOID)IOD_PCI0_IACK_QVA);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Write the target register.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg,
|
|||
|
(GidPrimary << 9)|(MidCpu1 << 6)|
|
|||
|
(GidPrimary << 3)|(MidCpu0)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the mask bits for target 0 and 1
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
(PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0,
|
|||
|
0
|
|||
|
);
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
(PVOID)&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1,
|
|||
|
0
|
|||
|
);
|
|||
|
|
|||
|
#endif //if defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
IodInitialized = TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpClearAllIods(
|
|||
|
IOD_CAP_ERR IodCapErrMask
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Clears specified CapErr bits on all IODs.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IodCapErrMask - Mask of bits to be cleared in each IOD_CAP_ERR.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
MC_ENUM_CONTEXT mcCtx;
|
|||
|
ULONG numIods;
|
|||
|
BOOLEAN bfoundIod;
|
|||
|
IOD_CAP_ERR IodCapErr;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Clear all the error conditions in CAP_ERR on all IODs
|
|||
|
// (Note - on 2 Mb Cached CPU, LostMcErr may also be set, so
|
|||
|
// clear everything to be fer-sure, fer-sure.)
|
|||
|
//
|
|||
|
|
|||
|
numIods = HalpMcBusEnumStart ( HalpIodMask, &mcCtx );
|
|||
|
|
|||
|
//
|
|||
|
// Clear all errors on all IODs.
|
|||
|
//
|
|||
|
|
|||
|
while ( bfoundIod = HalpMcBusEnum( &mcCtx ) ) {
|
|||
|
|
|||
|
//
|
|||
|
// Read it
|
|||
|
//
|
|||
|
|
|||
|
IodCapErr.all = READ_IOD_REGISTER_NEW( mcCtx.McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr );
|
|||
|
|
|||
|
//
|
|||
|
// Mask it.
|
|||
|
//
|
|||
|
|
|||
|
IodCapErr.all &= IodCapErrMask.all;
|
|||
|
|
|||
|
//
|
|||
|
// If there is anything to clear, then do it.
|
|||
|
//
|
|||
|
|
|||
|
if (IodCapErr.all != 0) {
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( mcCtx.McDeviceId,
|
|||
|
&((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr,
|
|||
|
IodCapErr.all );
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpInitializeIodVectorCSRs(
|
|||
|
MC_DEVICE_ID McDeviceId,
|
|||
|
ULONG PciBusNumber,
|
|||
|
va_list Arguments
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This enumeration routine initializes Interrupt Vector Table CSRS
|
|||
|
for the corresponding IOD.
|
|||
|
|
|||
|
The address used by an IOD during interrupt vector writes
|
|||
|
is:
|
|||
|
|
|||
|
39 38 32 31 12 11 6 5 2 1 0
|
|||
|
| | | | | | | | | | |
|
|||
|
===================================================================
|
|||
|
|0 | INT_ADDR_EXT | INT_ADDR_LO | TARGET ID | PCI BUS OFFSET | 00 |
|
|||
|
===================================================================
|
|||
|
|
|||
|
Where:
|
|||
|
INT_ADDR_EXT = 0 since our table resides in KSEG0_BASE.
|
|||
|
INT_ADDR_LO = upper 20 bits (4K Page Addr) of Table Physical Address
|
|||
|
TARGET_ID = MC_DEVICE_ID of Target CPU obtained from INT_TARG(0|1)
|
|||
|
PCI_BUS_OFFSET = Logical PCI bus number used as an offset into vector
|
|||
|
table by the interrupting IOD.
|
|||
|
|
|||
|
The assignment of PCI_BUS_OFFSET is based on the PCI bus number static
|
|||
|
variable. This number is incremented with each invokation of this routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McDeviceId - Supplies the MC Bus Device ID of the IOD to be intialized
|
|||
|
|
|||
|
PciBusNumber - Logical PCI Bus number (unused).
|
|||
|
|
|||
|
Arguments - Variable Arguments. None for this routine.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
IOD_INT_ADDR IodIntAddr;
|
|||
|
IOD_INT_ADDR_EXT IodIntAddrExt;
|
|||
|
IOD_INT_CONTROL IodIntControl;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the Interrupt Vector Table Address register
|
|||
|
// for this IOD.
|
|||
|
//
|
|||
|
|
|||
|
IodIntAddr.all =
|
|||
|
READ_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr );
|
|||
|
|
|||
|
IodIntAddr.Reserved1 = 0; // MBZ
|
|||
|
IodIntAddr.PciOffset = PciBusNumber; // Logical IOD #
|
|||
|
IodIntAddr.Reserved2 = 0; // MBZ
|
|||
|
IodIntAddr.IntAddrLo = ((ULONG)HalpIodPostedInterrupts / __4K);
|
|||
|
|
|||
|
//
|
|||
|
// Mask off the KSEG0_BASE to convert this to a physical
|
|||
|
// address.
|
|||
|
//
|
|||
|
|
|||
|
IodIntAddr.all &= ~KSEG0_BASE;
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr,
|
|||
|
IodIntAddr.all );
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the interrupt vector table Address Extension
|
|||
|
// register to zero since our address resides in KSEG0_BASE.
|
|||
|
//
|
|||
|
|
|||
|
IodIntAddrExt.all =
|
|||
|
READ_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt );
|
|||
|
|
|||
|
IodIntAddrExt.all = 0;
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
&((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt,
|
|||
|
IodIntAddrExt.all );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpIodInitializeSfwWindow(
|
|||
|
// ecrfix MC_DEVICE_ID McDeviceId,
|
|||
|
PWINDOW_CONTROL_REGISTERS WindowRegisters,
|
|||
|
IOD_WINDOW_NUMBER WindowNumber
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize the DMA Control software window registers for the specified
|
|||
|
DMA Window.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WindowRegisters - Supplies a pointer to the software window control.
|
|||
|
|
|||
|
WindowNumber - Supplies the window number initialized. (0 = Isa Dma
|
|||
|
Window, 1 = Master Dma Window).
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
switch( WindowNumber ){
|
|||
|
|
|||
|
//
|
|||
|
// The ISA DMA Window.
|
|||
|
//
|
|||
|
|
|||
|
case IodIsaWindow:
|
|||
|
|
|||
|
WindowRegisters->WindowBase = (PVOID)ISA_DMA_WINDOW_BASE;
|
|||
|
WindowRegisters->WindowSize = ISA_DMA_WINDOW_SIZE;
|
|||
|
WindowRegisters->TranslatedBaseRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T1base;
|
|||
|
WindowRegisters->WindowBaseRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base;
|
|||
|
WindowRegisters->WindowMaskRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1mask;
|
|||
|
WindowRegisters->WindowTbiaRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case IodMasterWindow:
|
|||
|
|
|||
|
WindowRegisters->WindowBase = (PVOID)MASTER_DMA_WINDOW_BASE;
|
|||
|
WindowRegisters->WindowSize = MASTER_DMA_WINDOW_SIZE;
|
|||
|
WindowRegisters->TranslatedBaseRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T0base;
|
|||
|
WindowRegisters->WindowBaseRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base;
|
|||
|
WindowRegisters->WindowMaskRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0mask;
|
|||
|
WindowRegisters->WindowTbiaRegister =
|
|||
|
&((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
|
|||
|
DbgPrint( "IodInitializeSfwWindow: Bad Window Number = %x\n",
|
|||
|
WindowNumber );
|
|||
|
|
|||
|
#endif //HALDBG
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpIodProgramDmaWindow(
|
|||
|
PWINDOW_CONTROL_REGISTERS WindowRegisters,
|
|||
|
PVOID MapRegisterBase
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Program the control windows in the hardware so that DMA can be started
|
|||
|
to the DMA window.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WindowRegisters - Supplies a pointer to the software window register
|
|||
|
control structure.
|
|||
|
|
|||
|
MapRegisterBase - Supplies the logical address of the scatter/gather
|
|||
|
array in system memory.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
IOD_WBASE Wbase;
|
|||
|
IOD_TBASE Tbase;
|
|||
|
IOD_WMASK Wmask;
|
|||
|
IOD_TBIA Tbia;
|
|||
|
|
|||
|
MC_ENUM_CONTEXT mcCtx;
|
|||
|
MC_DEVICE_ID McDeviceId;
|
|||
|
|
|||
|
//
|
|||
|
// Program the windows as specified by the caller.
|
|||
|
//
|
|||
|
|
|||
|
Wbase.all = 0;
|
|||
|
Wbase.Wen = 1;
|
|||
|
Wbase.SgEn = 1;
|
|||
|
Wbase.Wbase = (ULONG)(WindowRegisters->WindowBase) >> 20;
|
|||
|
|
|||
|
Wmask.all = 0;
|
|||
|
Wmask.Wmask = (WindowRegisters->WindowSize >> 20) - 1;
|
|||
|
|
|||
|
Tbase.all = 0;
|
|||
|
Tbase.Tbase = (ULONG)MapRegisterBase >> 10;
|
|||
|
|
|||
|
Tbia.all = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Dump the IOD registers.
|
|||
|
//
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
|
|||
|
// DumpAllIods( IodScatterGatherRegisters );
|
|||
|
|
|||
|
#endif //HALDBG
|
|||
|
|
|||
|
//
|
|||
|
// Loop through all of the Iods
|
|||
|
//
|
|||
|
// ecrfix - is it OK to do it one at a time this way?
|
|||
|
//
|
|||
|
|
|||
|
HalpMcBusEnumStart( HalpIodMask, &mcCtx );
|
|||
|
|
|||
|
while ( HalpMcBusEnum ( &mcCtx ) ) {
|
|||
|
|
|||
|
McDeviceId = mcCtx.McDeviceId;
|
|||
|
|
|||
|
//
|
|||
|
// Clear the window base, temporarily disabling transactions to this
|
|||
|
// DMA window.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
WindowRegisters->WindowBaseRegister, 0 );
|
|||
|
|
|||
|
//
|
|||
|
// Now program the window by writing the translated base, then the size
|
|||
|
// of the window in the mask register and finally the window base,
|
|||
|
// enabling both the window and scatter gather.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
WindowRegisters->TranslatedBaseRegister,
|
|||
|
Tbase.all );
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
WindowRegisters->WindowMaskRegister,
|
|||
|
Wmask.all );
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
WindowRegisters->WindowBaseRegister,
|
|||
|
Wbase.all );
|
|||
|
|
|||
|
//
|
|||
|
// Flush the volatile entries in this IOD's scatter/gather Tlb.
|
|||
|
//
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( McDeviceId,
|
|||
|
WindowRegisters->WindowTbiaRegister,
|
|||
|
Tbia.all );
|
|||
|
}
|
|||
|
|
|||
|
// ecrfix - we did it above. HalpIodInvalidateTlb( WindowRegisters );
|
|||
|
|
|||
|
//
|
|||
|
// Dump the IOD registers.
|
|||
|
//
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
|
|||
|
// DumpAllIods( IodScatterGatherRegisters | IodGeneralRegisters );
|
|||
|
|
|||
|
#endif //HALDBG
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpMcBusEnumStart(
|
|||
|
MC_DEVICE_MASK McDeviceMask,
|
|||
|
PMC_ENUM_CONTEXT McContext
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Given a particular MC Bus device mask:
|
|||
|
|
|||
|
* Set up state so that subsequent MC Bus devices can be enumerated
|
|||
|
by calling HalpMcBusEnum( McContext ).
|
|||
|
|
|||
|
* Return the first MC_DEVICE_ID in that mask via McContext.
|
|||
|
(ECRFIX: IFDEF out for now!)
|
|||
|
|
|||
|
N.B. The search will start with GID = 7, i.e., McDeviceMask<56>
|
|||
|
because the primary GID is 7.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McDeviceMask - Supplies a bitfield of MC Bus devices to be enumerated.
|
|||
|
|
|||
|
McContext - A structure that contains the MC_DEVICE_ID to be enumerated
|
|||
|
and associated enumerator state.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Number of MC Bus devices to be enumerated.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG count;
|
|||
|
|
|||
|
//
|
|||
|
// Intialize the bitmap from the McDeviceMask.
|
|||
|
// (Make a copy so that McDeviceMask is preserved for the caller.)
|
|||
|
//
|
|||
|
|
|||
|
McContext->tempMask = McDeviceMask;
|
|||
|
|
|||
|
// RtlInitializeBitMap(&McContext->McDeviceBitmap,
|
|||
|
HalpInitializeBitMap(&McContext->McDeviceBitmap,
|
|||
|
(PULONG) &McContext->tempMask,
|
|||
|
sizeof(MC_DEVICE_MASK) * 8);
|
|||
|
|
|||
|
//
|
|||
|
// Count the number of device to be enuerated
|
|||
|
//
|
|||
|
|
|||
|
count = HalpNumberOfSetBits (&McContext->McDeviceBitmap);
|
|||
|
|
|||
|
//
|
|||
|
|
|||
|
// Start looking at GID = 7.
|
|||
|
//
|
|||
|
|
|||
|
McContext->nextBit = GidPrimary * 8;
|
|||
|
|
|||
|
#if 0
|
|||
|
//
|
|||
|
// Find the first MC Bus device to be enumerated.
|
|||
|
//
|
|||
|
|
|||
|
McContext->nextBit = HalpFindSetBitsAndClear (&McContext->McDeviceBitmap,
|
|||
|
1,
|
|||
|
McContext->nextBit);
|
|||
|
|
|||
|
//
|
|||
|
// Convert first non-zero bit found to MC_DEVICE_ID
|
|||
|
//
|
|||
|
|
|||
|
McContext->McDeviceId.all = 0;
|
|||
|
McContext->McDeviceId.Gid = McContext->nextBit / 8;
|
|||
|
McContext->McDeviceId.Mid = McContext->nextBit % 8;
|
|||
|
#endif
|
|||
|
|
|||
|
return ( count );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
HalpMcBusEnum(
|
|||
|
PMC_ENUM_CONTEXT McContext
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Enumerate MC Bus devices until none are left
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McContext - A structure that contains the MC_DEVICE_ID to be enumerated
|
|||
|
and associated enumerator state.
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE, unless there were no more MC Bus devices to be enumerated,
|
|||
|
in which case, returns FALSE.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Find the next MC Bus device.
|
|||
|
//
|
|||
|
|
|||
|
McContext->nextBit = HalpFindSetBitsAndClear (&McContext->McDeviceBitmap,
|
|||
|
1,
|
|||
|
McContext->nextBit);
|
|||
|
|
|||
|
if ( McContext->nextBit != 0xffffffff) {
|
|||
|
|
|||
|
//
|
|||
|
// Convert the non-zero bit found to MC_DEVICE_ID
|
|||
|
//
|
|||
|
|
|||
|
McContext->McDeviceId.all = 0;
|
|||
|
McContext->McDeviceId.Gid = McContext->nextBit / 8;
|
|||
|
McContext->McDeviceId.Mid = McContext->nextBit % 8;
|
|||
|
|
|||
|
//
|
|||
|
// Since we just set nextBit to zero, we can start the
|
|||
|
// next search one bit higher. This will speed up the
|
|||
|
// next call to HalpMcBusEnum.
|
|||
|
//
|
|||
|
|
|||
|
McContext->nextBit++;
|
|||
|
|
|||
|
return ( TRUE );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
return ( FALSE) ;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpMcBusEnumAndCall(
|
|||
|
MC_DEVICE_MASK McDeviceMask,
|
|||
|
PMC_ENUM_ROUTINE McBusEnumRoutine,
|
|||
|
...
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Execute the Call routine for all devices in the MC device mask.
|
|||
|
This routine provides a general method to enumerate an MC_DEVICE_MASK
|
|||
|
and execute a caller-supplied routine for each device. A logical
|
|||
|
device number and variable arguments are passed to the routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McDeviceMask - Supplies a bitfield of MC Bus devices to be enumerated.
|
|||
|
|
|||
|
McBusEnumRoutine - Routine that is called for each MC Bus device.
|
|||
|
|
|||
|
... - Variable arguments passed by the caller.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
MC_ENUM_CONTEXT mcCtx;
|
|||
|
ULONG numIods;
|
|||
|
ULONG LogicalDeviceNumber = 0;
|
|||
|
va_list Arguments;
|
|||
|
|
|||
|
//
|
|||
|
// Intialize enumerator.
|
|||
|
//
|
|||
|
|
|||
|
numIods = HalpMcBusEnumStart ( McDeviceMask, &mcCtx );
|
|||
|
|
|||
|
//
|
|||
|
// Execute routine for each device.
|
|||
|
//
|
|||
|
|
|||
|
while ( HalpMcBusEnum( &mcCtx ) ) {
|
|||
|
va_start(Arguments, McBusEnumRoutine);
|
|||
|
McBusEnumRoutine( mcCtx.McDeviceId, LogicalDeviceNumber++, Arguments );
|
|||
|
va_end(Arguments);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpReadWhoAmI(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read the WHOAMI register.
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
Return Value:
|
|||
|
|
|||
|
The value of the WHOAMI.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
MC_DEVICE_ID McDeviceId;
|
|||
|
IOD_WHOAMI IodWhoAmI;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Initialize Id for IOD 0.
|
|||
|
//
|
|||
|
|
|||
|
McDeviceId.all = 0;
|
|||
|
McDeviceId.Gid = GidPrimary;
|
|||
|
McDeviceId.Mid = MidPci0;
|
|||
|
|
|||
|
|
|||
|
return (
|
|||
|
READ_IOD_REGISTER_NEW(
|
|||
|
McDeviceId,
|
|||
|
&((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI )
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
HalpIodInvalidateTlb(
|
|||
|
PWINDOW_CONTROL_REGISTERS WindowRegisters
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Invalidate the DMA Scatter/Gather TLB in all the IODs.
|
|||
|
The TLB is invalidated whenever the scatter/gather translation
|
|||
|
entries are modified.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WindowRegisters - Supplies a pointer to the software window register
|
|||
|
control structure.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Perform the S/G TLB invalidation
|
|||
|
//
|
|||
|
|
|||
|
IOD_TBIA Tbia;
|
|||
|
MC_ENUM_CONTEXT mcCtx;
|
|||
|
|
|||
|
Tbia.all = 0;
|
|||
|
|
|||
|
HalpMcBusEnumStart(HalpIodMask, &mcCtx);
|
|||
|
|
|||
|
while ( HalpMcBusEnum( &mcCtx ) ) {
|
|||
|
|
|||
|
WRITE_IOD_REGISTER_NEW( mcCtx.McDeviceId,
|
|||
|
WindowRegisters->WindowTbiaRegister,
|
|||
|
Tbia.all );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if HALDBG || DUMPIODS
|
|||
|
|
|||
|
IOD_REGISTER_CLASS DumpIodFlag = AllRegisters;
|
|||
|
|
|||
|
VOID
|
|||
|
DumpAllIods(
|
|||
|
IOD_REGISTER_CLASS RegistersToDump
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read the interesting Iod registers and print them to the debug port.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McDeviceId - Supplies the MC Bus Device ID of the IOD to be dumped
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
MC_ENUM_CONTEXT mcCtx;
|
|||
|
ULONG NumIods;
|
|||
|
|
|||
|
DbgPrint( "Dump All IODs: \n" );
|
|||
|
|
|||
|
NumIods = HalpMcBusEnumStart(HalpIodMask, &mcCtx);
|
|||
|
|
|||
|
DbgPrint( "Dump All IODs: (%d IODs)\n", NumIods );
|
|||
|
|
|||
|
while ( HalpMcBusEnum( &mcCtx ) ) {
|
|||
|
|
|||
|
DumpIod( mcCtx.McDeviceId,
|
|||
|
RegistersToDump );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
DumpIod(
|
|||
|
MC_DEVICE_ID McDeviceId,
|
|||
|
IOD_REGISTER_CLASS RegistersToDump
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read the interesting Iod registers and print them to the debug port.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
McDeviceId - Supplies the MC Bus Device ID of the IOD to be dumped
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PVOID RegisterQva;
|
|||
|
ULONG Value;
|
|||
|
|
|||
|
DbgPrint( "IOD (%x, %x) Register Dump: \n", McDeviceId.Gid, McDeviceId.Mid );
|
|||
|
|
|||
|
//
|
|||
|
// Dump the IOD General Control registers.
|
|||
|
//
|
|||
|
|
|||
|
if( (RegistersToDump & IodGeneralRegisters) != 0 ){
|
|||
|
|
|||
|
RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciRevision;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IodRevision = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->WhoAmI;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "WhoAmI = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->PciLat;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "PciLat = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->CapCtrl;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IodCtrl = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeMem;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "HaeMem = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->HaeIo;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "HaeIo = 0x%x\n", Value );
|
|||
|
|
|||
|
#if 0 // ecrfix - don't read this on PCI0 - creates an IACK cycle
|
|||
|
// on the EISA bus. Don't read this on PCI1,2,3, because
|
|||
|
// (apparently), it doesn't exist there.
|
|||
|
|
|||
|
RegisterQva = &((PIOD_GENERAL_CSRS)(IOD_GENERAL_CSRS_QVA))->IackSc;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IackSc = 0x%x\n", Value );
|
|||
|
#endif
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dump the IOD Interrupt registers.
|
|||
|
//
|
|||
|
|
|||
|
if( (RegistersToDump & IodInterruptRegisters) != 0 ){
|
|||
|
|
|||
|
RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntCtrl;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IntCtrl = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntReq;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IntReq = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntTarg;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IntTarg = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddr;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IntAddr = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntAddrExt;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IntAddrExt = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask0;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IntMask0 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_INT_CSRS)(IOD_INT_CSRS_QVA))->IntMask1;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "IntMask1 = 0x%x\n", Value );
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dump the IOD Diagnostic registers.
|
|||
|
//
|
|||
|
|
|||
|
if( (RegistersToDump & IodDiagnosticRegisters) != 0 ){
|
|||
|
|
|||
|
RegisterQva = &((PIOD_DIAG_CSRS)(IOD_DIAG_CSRS_QVA))->CapDiag;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "CapDiag = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_DIAG_CSRS)(IOD_DIAG_CSRS_QVA))->Scratch;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "Scratch = 0x%x\n", Value );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dump the IOD Error registers.
|
|||
|
//
|
|||
|
|
|||
|
if( (RegistersToDump & IodErrorRegisters) != 0 ){
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr0;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MCErr0 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->McErr1;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MCErr1 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->CapErr;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "CapErr = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->PciErr1;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "PciErr1 = 0x%x\n", Value );
|
|||
|
|
|||
|
#if 0 // CAP/MDP Bug
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaStat;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MdpaStat = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaSyn;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MdpaSyn = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpaDiag;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MdpaDiag = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbStat;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MdpbStat = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbSyn;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MdpbSyn = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_ERROR_CSRS)(IOD_ERROR_CSRS_QVA))->MdpbDiag;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "MdpbDiag = 0x%x\n", Value );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dump the PCI Scatter/Gather registers.
|
|||
|
//
|
|||
|
|
|||
|
if( (RegistersToDump & IodScatterGatherRegisters) != 0 ){
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Tbia;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "Tbia = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Hbase;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "Hbase = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W0base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W0mask;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W0mask = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T0base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "T0base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W1base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W1mask;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W1mask = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T1base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "T1base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W2base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W2mask;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W2mask = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T2base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "T2base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W3base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->W3mask;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "W3mask = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->T3base;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "T3base = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->Wdac;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "Wdac = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag0;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag0 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag1;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag1 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag2;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag2 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag3;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag3 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag4;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag4 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag5;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag5 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag6;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag6 = 0x%x\n", Value );
|
|||
|
|
|||
|
RegisterQva = &((PIOD_SG_CSRS)(IOD_SG_CSRS_QVA))->TbTag7;
|
|||
|
Value = READ_IOD_REGISTER_NEW( McDeviceId, RegisterQva );
|
|||
|
DbgPrint( "TbTag7 = 0x%x\n", Value );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Dump the IOD Reset register.
|
|||
|
//
|
|||
|
|
|||
|
if( (RegistersToDump & IodResetRegister) != 0 ){
|
|||
|
|
|||
|
RegisterQva = (PIOD_ELCR1)((ULONG)HalpEisaControlBase + 27);
|
|||
|
Value = (ULONG) READ_PORT_UCHAR( (PUCHAR) RegisterQva );
|
|||
|
DbgPrint( "ELCR2 = 0x%x\n", Value );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DbgPrint( "--end IOD Register dump\n\n" );
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#endif //HALDBG || DUMPIODS
|
|||
|
|