Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

564 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. ohci1394.c
  5. Abstract:
  6. 1394 Kernel Debugger DLL
  7. Author:
  8. Peter Binder (pbinder)
  9. Revision History:
  10. Date Who What
  11. ---------- --------- ------------------------------------------------------------
  12. 06/21/2001 pbinder having fun...
  13. --*/
  14. #define _OHCI1394_C
  15. #include "pch.h"
  16. #undef _OHCI1394_C
  17. ULONG
  18. FASTCALL
  19. Dbg1394_ByteSwap(
  20. IN ULONG Source
  21. )
  22. /*++
  23. Routine Description:
  24. The RtlUlongByteSwap function exchanges byte pairs 0:3 and 1:2 of
  25. Source and returns the resulting ULONG.
  26. Arguments:
  27. Source - 32-bit value to byteswap.
  28. Return Value:
  29. Swapped 32-bit value.
  30. --*/
  31. {
  32. ULONG swapped;
  33. swapped = ((Source) << (8 * 3)) |
  34. ((Source & 0x0000FF00) << (8 * 1)) |
  35. ((Source & 0x00FF0000) >> (8 * 1)) |
  36. ((Source) >> (8 * 3));
  37. return swapped;
  38. } // Dbg1394_ByteSwap
  39. ULONG
  40. Dbg1394_CalculateCrc(
  41. IN PULONG Quadlet,
  42. IN ULONG length
  43. )
  44. /*++
  45. Routine Description:
  46. This routine calculates a CRC for the pointer to the Quadlet data.
  47. Arguments:
  48. Quadlet - Pointer to data to CRC
  49. length - length of data to CRC
  50. Return Value:
  51. returns the CRC
  52. --*/
  53. {
  54. LONG temp;
  55. ULONG index;
  56. temp = index = 0;
  57. while (index < length) {
  58. temp = Dbg1394_Crc16(Quadlet[index++], temp);
  59. }
  60. return (temp);
  61. } // Dbg1394_CalculateCrc
  62. ULONG
  63. Dbg1394_Crc16(
  64. IN ULONG data,
  65. IN ULONG check
  66. )
  67. /*++
  68. Routine Description:
  69. This routine derives the 16 bit CRC as defined by IEEE 1212
  70. clause 8.1.5. (ISO/IEC 13213) First edition 1994-10-05.
  71. Arguments:
  72. data - ULONG data to derive CRC from
  73. check - check value
  74. Return Value:
  75. Returns CRC.
  76. --*/
  77. {
  78. LONG shift, sum, next;
  79. for (next = check, shift = 28; shift >= 0; shift -= 4) {
  80. sum = ((next >> 12) ^ (data >> shift)) & 0xf;
  81. next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
  82. }
  83. return(next & 0xFFFF);
  84. } // Dbg1394_Crc16
  85. NTSTATUS
  86. Dbg1394_ReadPhyRegister(
  87. PDEBUG_1394_DATA DebugData,
  88. ULONG Offset,
  89. PUCHAR pData
  90. )
  91. {
  92. union {
  93. ULONG AsUlong;
  94. PHY_CONTROL_REGISTER PhyControl;
  95. } u;
  96. ULONG retry = 0;
  97. u.AsUlong = 0;
  98. u.PhyControl.RdReg = TRUE;
  99. u.PhyControl.RegAddr = Offset;
  100. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl, u.AsUlong);
  101. retry = MAX_REGISTER_READS;
  102. do {
  103. u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl);
  104. } while ((!u.PhyControl.RdDone) && --retry);
  105. if (!retry) {
  106. return(STATUS_UNSUCCESSFUL);
  107. }
  108. *pData = (UCHAR)u.PhyControl.RdData;
  109. return(STATUS_SUCCESS);
  110. } // Dbg1394_ReadPhyRegister
  111. NTSTATUS
  112. Dbg1394_WritePhyRegister(
  113. PDEBUG_1394_DATA DebugData,
  114. ULONG Offset,
  115. UCHAR Data
  116. )
  117. {
  118. union {
  119. ULONG AsUlong;
  120. PHY_CONTROL_REGISTER PhyControl;
  121. } u;
  122. ULONG retry = 0;
  123. u.AsUlong = 0;
  124. u.PhyControl.WrReg = TRUE;
  125. u.PhyControl.RegAddr = Offset;
  126. u.PhyControl.WrData = Data;
  127. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl, u.AsUlong);
  128. retry = MAX_REGISTER_READS;
  129. do {
  130. u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyControl);
  131. } while (u.PhyControl.WrReg && --retry);
  132. if (!retry) {
  133. return(STATUS_UNSUCCESSFUL);
  134. }
  135. return(STATUS_SUCCESS);
  136. } // Dbg1394_WritePhyRegister
  137. BOOLEAN
  138. Dbg1394_InitializeController(
  139. IN PDEBUG_1394_DATA DebugData,
  140. IN PDEBUG_1394_PARAMETERS DebugParameters
  141. )
  142. {
  143. BOOLEAN bReturn = TRUE;
  144. ULONG ulVersion;
  145. UCHAR MajorVersion;
  146. UCHAR MinorVersion;
  147. ULONG ReadRetry;
  148. PHYSICAL_ADDRESS physAddr;
  149. UCHAR Data;
  150. NTSTATUS ntStatus;
  151. union {
  152. ULONG AsUlong;
  153. HC_CONTROL_REGISTER HCControl;
  154. LINK_CONTROL_REGISTER LinkControl;
  155. NODE_ID_REGISTER NodeId;
  156. CONFIG_ROM_INFO ConfigRomHeader;
  157. BUS_OPTIONS_REGISTER BusOptions;
  158. IMMEDIATE_ENTRY CromEntry;
  159. DIRECTORY_INFO DirectoryInfo;
  160. } u;
  161. // initialize our bus info
  162. DebugData->Config.Tag = DEBUG_1394_CONFIG_TAG;
  163. DebugData->Config.MajorVersion = DEBUG_1394_MAJOR_VERSION;
  164. DebugData->Config.MinorVersion = DEBUG_1394_MINOR_VERSION;
  165. DebugData->Config.Id = DebugParameters->Id;
  166. DebugData->Config.BusPresent = FALSE;
  167. DebugData->Config.SendPacket = MmGetPhysicalAddress(&DebugData->SendPacket);
  168. DebugData->Config.ReceivePacket = MmGetPhysicalAddress(&DebugData->ReceivePacket);
  169. // get our base address
  170. DebugData->BaseAddress = \
  171. (POHCI_REGISTER_MAP)DebugParameters->DbgDeviceDescriptor.BaseAddress[0].TranslatedAddress;
  172. // get our version
  173. ulVersion = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->Version);
  174. MajorVersion = (UCHAR)(ulVersion >> 16);
  175. MinorVersion = (UCHAR)ulVersion;
  176. // make sure we have a valid version
  177. if (MajorVersion != 1) { // INVESTIGATE
  178. bReturn = FALSE;
  179. goto Exit_Dbg1394_InitializeController;
  180. }
  181. // soft reset to initialize the controller
  182. u.AsUlong = 0;
  183. u.HCControl.SoftReset = TRUE;
  184. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
  185. // wait until reset complete - ??
  186. ReadRetry = 1000; // ??
  187. do {
  188. u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet);
  189. Dbg1394_StallExecution(1);
  190. } while ((u.HCControl.SoftReset) && (--ReadRetry));
  191. // see if reset succeeded
  192. if (ReadRetry == 0) {
  193. bReturn = FALSE;
  194. goto Exit_Dbg1394_InitializeController;
  195. }
  196. // what's this do???
  197. u.AsUlong = 0;
  198. u.HCControl.Lps = TRUE;
  199. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
  200. Dbg1394_StallExecution(20);
  201. // initialize HCControl register
  202. u.AsUlong = 0;
  203. u.HCControl.NoByteSwapData = TRUE;
  204. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlClear, u.AsUlong);
  205. u.AsUlong = 0;
  206. u.HCControl.PostedWriteEnable = TRUE;
  207. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
  208. // setup the link control
  209. u.AsUlong = 0x0;
  210. u.LinkControl.CycleTimerEnable = TRUE;
  211. u.LinkControl.CycleMaster = TRUE;
  212. u.LinkControl.RcvPhyPkt = TRUE;
  213. u.LinkControl.RcvSelfId = TRUE;
  214. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->LinkControlClear, u.AsUlong);
  215. u.AsUlong = 0;
  216. u.LinkControl.CycleTimerEnable = TRUE;
  217. u.LinkControl.CycleMaster = TRUE;
  218. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->LinkControlSet, u.AsUlong);
  219. // set the bus number (hardcoded to 0x3FF) - ??? what about node id??
  220. u.AsUlong = 0;
  221. u.NodeId.BusId = (USHORT)0x3FF;
  222. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->NodeId, u.AsUlong);
  223. // ???????????????
  224. // IA64 BUGBUG assumes that our global buffers, that were loaded with our
  225. // image are placed < 32bit memory
  226. // ???????????????
  227. // do something with the crom...
  228. // 0xf0000404 - bus id register
  229. DebugData->CromBuffer[1] = 0x31333934;
  230. // 0xf0000408 - bus options register
  231. u.AsUlong = Dbg1394_ByteSwap(READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->BusOptions));
  232. u.BusOptions.Pmc = FALSE;
  233. u.BusOptions.Bmc = FALSE;
  234. u.BusOptions.Isc = FALSE;
  235. u.BusOptions.Cmc = FALSE;
  236. u.BusOptions.Irmc = FALSE;
  237. u.BusOptions.g = 1;
  238. DebugData->CromBuffer[2] = Dbg1394_ByteSwap(u.AsUlong);
  239. // 0xf000040c - global unique id hi
  240. u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidHi);
  241. DebugData->CromBuffer[3] = u.AsUlong;
  242. // 0xf0000410 - global unique id lo
  243. u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidLo);
  244. DebugData->CromBuffer[4] = u.AsUlong;
  245. // 0xf0000400 - config rom header - set last to calculate CRC!
  246. u.AsUlong = 0;
  247. u.ConfigRomHeader.CRI_Info_Length = 4;
  248. u.ConfigRomHeader.CRI_CRC_Length = 4;
  249. u.ConfigRomHeader.u.CRI_CRC_Value = (USHORT)Dbg1394_CalculateCrc( &DebugData->CromBuffer[1],
  250. u.ConfigRomHeader.CRI_CRC_Length
  251. );
  252. DebugData->CromBuffer[0] = u.AsUlong;
  253. // 0xf0000418 - node capabilities
  254. DebugData->CromBuffer[6] = 0xC083000C;
  255. // 0xf000041C - module vendor id
  256. DebugData->CromBuffer[7] = 0xF2500003;
  257. // 0xf0000420 - extended key
  258. DebugData->CromBuffer[8] = 0xF250001C;
  259. // 0xf0000424 - debug key
  260. DebugData->CromBuffer[9] = 0x0200001D;
  261. // 0xf0000428 - debug value
  262. physAddr = MmGetPhysicalAddress(&DebugData->Config);
  263. u.AsUlong = (ULONG)physAddr.LowPart;
  264. u.CromEntry.IE_Key = 0x1E;
  265. DebugData->CromBuffer[10] = Dbg1394_ByteSwap(u.AsUlong);
  266. // 0xf0000414 - root directory header - set last to calculate CRC!
  267. u.AsUlong = 0;
  268. u.DirectoryInfo.DI_Length = 5;
  269. u.DirectoryInfo.u.DI_CRC = (USHORT)Dbg1394_CalculateCrc( &DebugData->CromBuffer[6],
  270. u.DirectoryInfo.DI_Length
  271. );
  272. DebugData->CromBuffer[5] = Dbg1394_ByteSwap(u.AsUlong);
  273. // write the first few registers
  274. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->ConfigRomHeader, DebugData->CromBuffer[0]);
  275. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->BusId, DebugData->CromBuffer[1]);
  276. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->BusOptions, DebugData->CromBuffer[2]);
  277. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidHi, DebugData->CromBuffer[3]);
  278. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->GuidLo, DebugData->CromBuffer[4]);
  279. // set our crom
  280. physAddr = MmGetPhysicalAddress(&DebugData->CromBuffer);
  281. u.AsUlong = (ULONG)physAddr.LowPart; // FIXFIX quadpart to ulong??
  282. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->ConfigRomMap, u.AsUlong);
  283. // disable all interrupts. wdm driver will enable them later - ??
  284. u.AsUlong = 0xFFFFFFFF;
  285. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->IntMaskClear, u.AsUlong);
  286. // enable the link
  287. u.AsUlong = 0;
  288. u.HCControl.LinkEnable = TRUE;
  289. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet, u.AsUlong);
  290. Dbg1394_StallExecution(1000);
  291. // enable access filters to all nodes
  292. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterLoSet, 0xFFFFFFFF);
  293. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterHiSet, 0xFFFFFFFF);
  294. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterHiSet, 0xFFFFFFFF);
  295. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterLoSet, 0xFFFFFFFF);
  296. // hard reset on the bus
  297. ntStatus = Dbg1394_ReadPhyRegister(DebugData, 1, &Data);
  298. if (NT_SUCCESS(ntStatus)) {
  299. Data |= PHY_INITIATE_BUS_RESET;
  300. Dbg1394_WritePhyRegister(DebugData, 1, Data);
  301. Dbg1394_StallExecution(1000);
  302. }
  303. else {
  304. bReturn = FALSE;
  305. }
  306. Exit_Dbg1394_InitializeController:
  307. return(bReturn);
  308. } // Dbg1394_InitializeController
  309. ULONG // ?? need to look into this
  310. Dbg1394_StallExecution(
  311. ULONG LoopCount
  312. )
  313. {
  314. ULONG i,j,b,k,l;
  315. b = 1;
  316. for (k=0;k<LoopCount;k++) {
  317. for (i=1;i<100000;i++) {
  318. PAUSE_PROCESSOR
  319. b=b* (i>>k);
  320. }
  321. };
  322. return(b);
  323. } // Dbg1394_StallExecution
  324. void
  325. Dbg1394_EnablePhysicalAccess(
  326. IN PDEBUG_1394_DATA DebugData
  327. )
  328. {
  329. union {
  330. ULONG AsUlong;
  331. INT_EVENT_MASK_REGISTER IntEvent;
  332. HC_CONTROL_REGISTER HCControl;
  333. } u;
  334. // see if ohci1394 is being loaded...
  335. u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->HCControlSet);
  336. if (!u.HCControl.LinkEnable || !u.HCControl.Lps || u.HCControl.SoftReset) {
  337. return;
  338. }
  339. // only clear the bus reset interrupt if ohci1394 isn't loaded...
  340. // if (DebugData->Config.BusPresent == FALSE) {
  341. // if the bus reset interrupt is not cleared, we have to clear it...
  342. u.AsUlong = READ_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->IntEventSet);
  343. if (u.IntEvent.BusReset) {
  344. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->IntEventClear, PHY_BUS_RESET_INT);
  345. }
  346. // }
  347. // we might need to reenable physical access, if so, do it.
  348. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterHiSet, 0xFFFFFFFF);
  349. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->AsynchReqFilterLoSet, 0xFFFFFFFF);
  350. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterHiSet, 0xFFFFFFFF);
  351. WRITE_REGISTER_ULONG((PULONG)&DebugData->BaseAddress->PhyReqFilterLoSet, 0xFFFFFFFF);
  352. return;
  353. } // Dbg1394_EnablePhysicalAccess
  354. ULONG
  355. Dbg1394_ReadPacket(
  356. PDEBUG_1394_DATA DebugData,
  357. OUT PKD_PACKET PacketHeader,
  358. OUT PSTRING MessageHeader,
  359. OUT PSTRING MessageData,
  360. BOOLEAN Wait
  361. )
  362. // KDP_PACKET_RESEND - if resend is required. = 2 = CP_GET_ERROR
  363. // KDP_PACKET_TIMEOUT - if timeout. = 1 = CP_GET_NODATA
  364. // KDP_PACKET_RECEIVED - if packet received. = 0 = CP_GET_SUCCESS
  365. {
  366. ULONG timeoutLimit = 0;
  367. do {
  368. // make sure our link is enabled..
  369. Dbg1394_EnablePhysicalAccess(Kd1394Data);
  370. if (DebugData->ReceivePacket.TransferStatus == STATUS_PENDING) {
  371. *KdDebuggerNotPresent = FALSE;
  372. SharedUserData->KdDebuggerEnabled |= 0x00000002;
  373. RtlCopyMemory( PacketHeader,
  374. &DebugData->ReceivePacket.Packet[0],
  375. sizeof(KD_PACKET)
  376. );
  377. // make sure we have a valid PacketHeader
  378. if (DebugData->ReceivePacket.Length < sizeof(KD_PACKET)) {
  379. // short packet, we are done...
  380. DebugData->ReceivePacket.TransferStatus = STATUS_SUCCESS;
  381. return(KDP_PACKET_RESEND);
  382. }
  383. if (MessageHeader) {
  384. RtlCopyMemory( MessageHeader->Buffer,
  385. &DebugData->ReceivePacket.Packet[sizeof(KD_PACKET)],
  386. MessageHeader->MaximumLength
  387. );
  388. if (DebugData->ReceivePacket.Length <= (USHORT)(sizeof(KD_PACKET)+MessageHeader->MaximumLength)) {
  389. DebugData->ReceivePacket.TransferStatus = STATUS_SUCCESS;
  390. return(KDP_PACKET_RECEIVED);
  391. }
  392. if (MessageData) {
  393. RtlCopyMemory( MessageData->Buffer,
  394. &DebugData->ReceivePacket.Packet[sizeof(KD_PACKET) + MessageHeader->MaximumLength],
  395. DebugData->ReceivePacket.Length - (sizeof(KD_PACKET) + MessageHeader->MaximumLength)
  396. );
  397. }
  398. }
  399. DebugData->ReceivePacket.TransferStatus = STATUS_SUCCESS;
  400. return(KDP_PACKET_RECEIVED);
  401. }
  402. timeoutLimit++;
  403. if (Wait == FALSE) {
  404. return(KDP_PACKET_RESEND);
  405. }
  406. } while (timeoutLimit <= TIMEOUT_COUNT);
  407. return(KDP_PACKET_TIMEOUT);
  408. } // Dbg1394_ReadPacket