/*++ 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>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