windows-nt/Source/XPSP1/NT/base/boot/kd1394/ohci1394.c
2020-09-26 16:20:57 +08:00

565 lines
15 KiB
C

/*++
Copyright (c) 1998-2001 Microsoft Corporation
Module Name:
ohci1394.c
Abstract:
1394 Kernel Debugger DLL
Author:
Peter Binder (pbinder)
Revision History:
Date Who What
---------- --------- ------------------------------------------------------------
06/21/2001 pbinder having fun...
--*/
#define _OHCI1394_C
#include "pch.h"
#undef _OHCI1394_C
ULONG
FASTCALL
Dbg1394_ByteSwap(
IN ULONG Source
)
/*++
Routine Description:
The RtlUlongByteSwap function exchanges byte pairs 0:3 and 1:2 of
Source and returns the resulting ULONG.
Arguments:
Source - 32-bit value to byteswap.
Return Value:
Swapped 32-bit value.
--*/
{
ULONG swapped;
swapped = ((Source) << (8 * 3)) |
((Source & 0x0000FF00) << (8 * 1)) |
((Source & 0x00FF0000) >> (8 * 1)) |
((Source) >> (8 * 3));
return swapped;
} // Dbg1394_ByteSwap
ULONG
Dbg1394_CalculateCrc(
IN PULONG Quadlet,
IN ULONG length
)
/*++
Routine Description:
This routine calculates a CRC for the pointer to the Quadlet data.
Arguments:
Quadlet - Pointer to data to CRC
length - length of data to CRC
Return Value:
returns the CRC
--*/
{
LONG temp;
ULONG index;
temp = index = 0;
while (index < length) {
temp = Dbg1394_Crc16(Quadlet[index++], temp);
}
return (temp);
} // Dbg1394_CalculateCrc
ULONG
Dbg1394_Crc16(
IN ULONG data,
IN ULONG check
)
/*++
Routine Description:
This routine derives the 16 bit CRC as defined by IEEE 1212
clause 8.1.5. (ISO/IEC 13213) First edition 1994-10-05.
Arguments:
data - ULONG data to derive CRC from
check - check value
Return Value:
Returns CRC.
--*/
{
LONG shift, sum, next;
for (next = check, shift = 28; shift >= 0; shift -= 4) {
sum = ((next >> 12) ^ (data >> shift)) & 0xf;
next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
}
return(next & 0xFFFF);
} // Dbg1394_Crc16
NTSTATUS
Dbg1394_ReadPhyRegister(
PDEBUG_1394_DATA DebugData,
ULONG Offset,
PUCHAR pData
)
{
union {
ULONG AsUlong;
PHY_CONTROL_REGISTER PhyControl;
} u;
ULONG retry = 0;
u.AsUlong = 0;
u.PhyControl.RdReg = TRUE;
u.PhyControl.RegAddr = Offset;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl, u.AsUlong);
retry = MAX_REGISTER_READS;
do {
u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl);
} while ((!u.PhyControl.RdDone) && --retry);
if (!retry) {
return(STATUS_UNSUCCESSFUL);
}
*pData = (UCHAR)u.PhyControl.RdData;
return(STATUS_SUCCESS);
} // Dbg1394_ReadPhyRegister
NTSTATUS
Dbg1394_WritePhyRegister(
PDEBUG_1394_DATA DebugData,
ULONG Offset,
UCHAR Data
)
{
union {
ULONG AsUlong;
PHY_CONTROL_REGISTER PhyControl;
} u;
ULONG retry = 0;
u.AsUlong = 0;
u.PhyControl.WrReg = TRUE;
u.PhyControl.RegAddr = Offset;
u.PhyControl.WrData = Data;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl, u.AsUlong);
retry = MAX_REGISTER_READS;
do {
u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl);
} while (u.PhyControl.WrReg && --retry);
if (!retry) {
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
} // Dbg1394_WritePhyRegister
BOOLEAN
Dbg1394_InitializeController(
IN PDEBUG_1394_DATA DebugData,
IN PDEBUG_1394_PARAMETERS DebugParameters
)
{
BOOLEAN bReturn = TRUE;
ULONG ulVersion;
UCHAR MajorVersion;
UCHAR MinorVersion;
ULONG ReadRetry;
PHYSICAL_ADDRESS physAddr;
UCHAR Data;
NTSTATUS ntStatus;
union {
ULONG AsUlong;
HC_CONTROL_REGISTER HCControl;
LINK_CONTROL_REGISTER LinkControl;
NODE_ID_REGISTER NodeId;
CONFIG_ROM_INFO ConfigRomHeader;
BUS_OPTIONS_REGISTER BusOptions;
IMMEDIATE_ENTRY CromEntry;
DIRECTORY_INFO DirectoryInfo;
} u;
// initialize our bus info
DebugData->Config.Tag = DEBUG_1394_CONFIG_TAG;
DebugData->Config.MajorVersion = DEBUG_1394_MAJOR_VERSION;
DebugData->Config.MinorVersion = DEBUG_1394_MINOR_VERSION;
DebugData->Config.Id = DebugParameters->Id;
DebugData->Config.BusPresent = FALSE;
DebugData->Config.SendPacket = MmGetPhysicalAddress(&DebugData->SendPacket);
DebugData->Config.ReceivePacket = MmGetPhysicalAddress(&DebugData->ReceivePacket);
// get our base address
DebugData->BaseAddress = \
(POHCI_REGISTER_MAP)DebugParameters->DbgDeviceDescriptor.BaseAddress[0].TranslatedAddress;
// get our version
ulVersion = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->Version);
MajorVersion = (UCHAR)(ulVersion >> 16);
MinorVersion = (UCHAR)ulVersion;
// make sure we have a valid version
if (MajorVersion != 1) { // INVESTIGATE
bReturn = FALSE;
goto Exit_Dbg1394_InitializeController;
}
// soft reset to initialize the controller
u.AsUlong = 0;
u.HCControl.SoftReset = TRUE;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
// wait until reset complete - ??
ReadRetry = 1000; // ??
do {
u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet);
Dbg1394_StallExecution(1);
} while ((u.HCControl.SoftReset) && (--ReadRetry));
// see if reset succeeded
if (ReadRetry == 0) {
bReturn = FALSE;
goto Exit_Dbg1394_InitializeController;
}
// what's this do???
u.AsUlong = 0;
u.HCControl.Lps = TRUE;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
Dbg1394_StallExecution(20);
// initialize HCControl register
u.AsUlong = 0;
u.HCControl.NoByteSwapData = TRUE;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlClear, u.AsUlong);
u.AsUlong = 0;
u.HCControl.PostedWriteEnable = TRUE;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
// setup the link control
u.AsUlong = 0x0;
u.LinkControl.CycleTimerEnable = TRUE;
u.LinkControl.CycleMaster = TRUE;
u.LinkControl.RcvPhyPkt = TRUE;
u.LinkControl.RcvSelfId = TRUE;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->LinkControlClear, u.AsUlong);
u.AsUlong = 0;
u.LinkControl.CycleTimerEnable = TRUE;
u.LinkControl.CycleMaster = TRUE;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->LinkControlSet, u.AsUlong);
// set the bus number (hardcoded to 0x3FF) - ??? what about node id??
u.AsUlong = 0;
u.NodeId.BusId = (USHORT)0x3FF;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->NodeId, u.AsUlong);
// ???????????????
// IA64 BUGBUG assumes that our global buffers, that were loaded with our
// image are placed < 32bit memory
// ???????????????
// do something with the crom...
// 0xf0000404 - bus id register
DebugData->CromBuffer[1] = 0x31333934;
// 0xf0000408 - bus options register
u.AsUlong = Dbg1394_ByteSwap(READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->BusOptions));
u.BusOptions.Pmc = FALSE;
u.BusOptions.Bmc = FALSE;
u.BusOptions.Isc = FALSE;
u.BusOptions.Cmc = FALSE;
u.BusOptions.Irmc = FALSE;
u.BusOptions.g = 1;
DebugData->CromBuffer[2] = Dbg1394_ByteSwap(u.AsUlong);
// 0xf000040c - global unique id hi
u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidHi);
DebugData->CromBuffer[3] = u.AsUlong;
// 0xf0000410 - global unique id lo
u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidLo);
DebugData->CromBuffer[4] = u.AsUlong;
// 0xf0000400 - config rom header - set last to calculate CRC!
u.AsUlong = 0;
u.ConfigRomHeader.CRI_Info_Length = 4;
u.ConfigRomHeader.CRI_CRC_Length = 4;
u.ConfigRomHeader.u.CRI_CRC_Value = (USHORT)Dbg1394_CalculateCrc( &DebugData->CromBuffer[1],
u.ConfigRomHeader.CRI_CRC_Length
);
DebugData->CromBuffer[0] = u.AsUlong;
// 0xf0000418 - node capabilities
DebugData->CromBuffer[6] = 0xC083000C;
// 0xf000041C - module vendor id
DebugData->CromBuffer[7] = 0xF2500003;
// 0xf0000420 - extended key
DebugData->CromBuffer[8] = 0xF250001C;
// 0xf0000424 - debug key
DebugData->CromBuffer[9] = 0x0200001D;
// 0xf0000428 - debug value
physAddr = MmGetPhysicalAddress(&DebugData->Config);
u.AsUlong = (ULONG)physAddr.LowPart;
u.CromEntry.IE_Key = 0x1E;
DebugData->CromBuffer[10] = Dbg1394_ByteSwap(u.AsUlong);
// 0xf0000414 - root directory header - set last to calculate CRC!
u.AsUlong = 0;
u.DirectoryInfo.DI_Length = 5;
u.DirectoryInfo.u.DI_CRC = (USHORT)Dbg1394_CalculateCrc( &DebugData->CromBuffer[6],
u.DirectoryInfo.DI_Length
);
DebugData->CromBuffer[5] = Dbg1394_ByteSwap(u.AsUlong);
// write the first few registers
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->ConfigRomHeader, DebugData->CromBuffer[0]);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->BusId, DebugData->CromBuffer[1]);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->BusOptions, DebugData->CromBuffer[2]);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidHi, DebugData->CromBuffer[3]);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidLo, DebugData->CromBuffer[4]);
// set our crom
physAddr = MmGetPhysicalAddress(&DebugData->CromBuffer);
u.AsUlong = (ULONG)physAddr.LowPart; // FIXFIX quadpart to ulong??
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->ConfigRomMap, u.AsUlong);
// disable all interrupts. wdm driver will enable them later - ??
u.AsUlong = 0xFFFFFFFF;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->IntMaskClear, u.AsUlong);
// enable the link
u.AsUlong = 0;
u.HCControl.LinkEnable = TRUE;
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
Dbg1394_StallExecution(1000);
// enable access filters to all nodes
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterLoSet, 0xFFFFFFFF);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterHiSet, 0xFFFFFFFF);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterHiSet, 0xFFFFFFFF);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterLoSet, 0xFFFFFFFF);
// hard reset on the bus
ntStatus = Dbg1394_ReadPhyRegister(DebugData, 1, &Data);
if (NT_SUCCESS(ntStatus)) {
Data |= PHY_INITIATE_BUS_RESET;
Dbg1394_WritePhyRegister(DebugData, 1, Data);
Dbg1394_StallExecution(1000);
}
else {
bReturn = FALSE;
}
Exit_Dbg1394_InitializeController:
return(bReturn);
} // Dbg1394_InitializeController
ULONG // ?? need to look into this
Dbg1394_StallExecution(
ULONG LoopCount
)
{
ULONG i,j,b,k,l;
b = 1;
for (k=0;k<LoopCount;k++) {
for (i=1;i<100000;i++) {
PAUSE_PROCESSOR
b=b* (i>>k);
}
};
return(b);
} // Dbg1394_StallExecution
void
Dbg1394_EnablePhysicalAccess(
IN PDEBUG_1394_DATA DebugData
)
{
union {
ULONG AsUlong;
INT_EVENT_MASK_REGISTER IntEvent;
HC_CONTROL_REGISTER HCControl;
} u;
// see if ohci1394 is being loaded...
u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet);
if (!u.HCControl.LinkEnable || !u.HCControl.Lps || u.HCControl.SoftReset) {
return;
}
// only clear the bus reset interrupt if ohci1394 isn't loaded...
// if (DebugData->Config.BusPresent == FALSE) {
// if the bus reset interrupt is not cleared, we have to clear it...
u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->IntEventSet);
if (u.IntEvent.BusReset) {
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->IntEventClear, PHY_BUS_RESET_INT);
}
// }
// we might need to reenable physical access, if so, do it.
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterHiSet, 0xFFFFFFFF);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterLoSet, 0xFFFFFFFF);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterHiSet, 0xFFFFFFFF);
WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterLoSet, 0xFFFFFFFF);
return;
} // Dbg1394_EnablePhysicalAccess
ULONG
Dbg1394_ReadPacket(
PDEBUG_1394_DATA DebugData,
OUT PKD_PACKET PacketHeader,
OUT PSTRING MessageHeader,
OUT PSTRING MessageData,
BOOLEAN Wait
)
// KDP_PACKET_RESEND - if resend is required. = 2 = CP_GET_ERROR
// KDP_PACKET_TIMEOUT - if timeout. = 1 = CP_GET_NODATA
// KDP_PACKET_RECEIVED - if packet received. = 0 = CP_GET_SUCCESS
{
ULONG timeoutLimit = 0;
do {
// make sure our link is enabled..
Dbg1394_EnablePhysicalAccess(Kd1394Data);
if (DebugData->ReceivePacket.TransferStatus == STATUS_PENDING) {
*KdDebuggerNotPresent = FALSE;
SharedUserData->KdDebuggerEnabled |= 0x00000002;
RtlCopyMemory( PacketHeader,
&DebugData->ReceivePacket.Packet[0],
sizeof(KD_PACKET)
);
// make sure we have a valid PacketHeader
if (DebugData->ReceivePacket.Length < sizeof(KD_PACKET)) {
// short packet, we are done...
DebugData->ReceivePacket.TransferStatus = STATUS_SUCCESS;
return(KDP_PACKET_RESEND);
}
if (MessageHeader) {
RtlCopyMemory( MessageHeader->Buffer,
&DebugData->ReceivePacket.Packet[sizeof(KD_PACKET)],
MessageHeader->MaximumLength
);
if (DebugData->ReceivePacket.Length <= (USHORT)(sizeof(KD_PACKET)+MessageHeader->MaximumLength)) {
DebugData->ReceivePacket.TransferStatus = STATUS_SUCCESS;
return(KDP_PACKET_RECEIVED);
}
if (MessageData) {
RtlCopyMemory( MessageData->Buffer,
&DebugData->ReceivePacket.Packet[sizeof(KD_PACKET) + MessageHeader->MaximumLength],
DebugData->ReceivePacket.Length - (sizeof(KD_PACKET) + MessageHeader->MaximumLength)
);
}
}
DebugData->ReceivePacket.TransferStatus = STATUS_SUCCESS;
return(KDP_PACKET_RECEIVED);
}
timeoutLimit++;
if (Wait == FALSE) {
return(KDP_PACKET_RESEND);
}
} while (timeoutLimit <= TIMEOUT_COUNT);
return(KDP_PACKET_TIMEOUT);
} // Dbg1394_ReadPacket