565 lines
15 KiB
C
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
|
|
|