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.

503 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. kd1394.c
  5. Abstract:
  6. 1394 Kernel Debugger DLL
  7. Author:
  8. George Chrysanthakopoulos (georgioc) Feb-2000
  9. Revision History:
  10. Date Who What
  11. ---------- --------- ------------------------------------------------------------
  12. 06/19/2001 pbinder cleanup
  13. --*/
  14. #define _KD1394_C
  15. #include "pch.h"
  16. #undef _KD1394_C
  17. BOOLEAN
  18. Kd1394pInitialize(
  19. IN PDEBUG_1394_PARAMETERS DebugParameters,
  20. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  21. )
  22. /*++
  23. Routine Description:
  24. This routine enumerates the bus controller of DebugParameters.BusType, using
  25. the appropriate ClassCode (generic enumeration). If PCI addressing info was
  26. found on the Options String passed by the Loader, will use this and go directly
  27. to that bus number, slot, function to setup that controller.
  28. Arguments:
  29. DebugParameters - Supplies Debug parameters parsed from Options string
  30. LoaderBlock - Supplies a pointer to the LOADER_PARAMETER_BLOCK passed
  31. in from the OS Loader.
  32. Return Value:
  33. None.
  34. --*/
  35. {
  36. NTSTATUS ntStatus;
  37. ULONG maxPhys;
  38. //
  39. // Find the controller, setup the PCI registers for it
  40. // and do bus specific initialization
  41. //
  42. DebugParameters->DbgDeviceDescriptor.Memory.Length = sizeof(DEBUG_1394_DATA);
  43. ntStatus = KdSetupPciDeviceForDebugging( LoaderBlock,
  44. &DebugParameters->DbgDeviceDescriptor
  45. );
  46. if (!NT_SUCCESS(ntStatus)) {
  47. return(FALSE);
  48. }
  49. Kd1394Data = DebugParameters->DbgDeviceDescriptor.Memory.VirtualAddress;
  50. RtlZeroMemory(Kd1394Data, sizeof(DEBUG_1394_DATA));
  51. return(Dbg1394_InitializeController(Kd1394Data, DebugParameters));
  52. } // Kd1394pInitialize
  53. NTSTATUS
  54. KdD0Transition(
  55. void
  56. )
  57. /*++
  58. Routine Description:
  59. The PCI driver (or relevant bus driver) will call this API after it
  60. processes a D0 IRP for this device
  61. Arguments:
  62. None
  63. Return Value:
  64. STATUS_SUCCESS, or appropriate error status
  65. --*/
  66. {
  67. LOADER_PARAMETER_BLOCK LoaderBlock = {0};
  68. // see if we need to activate the debugger
  69. if (Kd1394Parameters.DebuggerActive == FALSE) {
  70. if (Kd1394pInitialize(&Kd1394Parameters, &LoaderBlock)) {
  71. Kd1394Parameters.DebuggerActive = TRUE;
  72. }
  73. }
  74. return(STATUS_SUCCESS);
  75. } // KdD0Transition
  76. NTSTATUS
  77. KdD3Transition(
  78. void
  79. )
  80. /*++
  81. Routine Description:
  82. The PCI driver (or relevant bus driver) will call this API before it
  83. processes a D3 IRP for this device
  84. Arguments:
  85. None
  86. Return Value:
  87. STATUS_SUCCESS, or appropriate error status
  88. --*/
  89. {
  90. Kd1394Parameters.DebuggerActive = FALSE;
  91. return(STATUS_SUCCESS);
  92. } // KdD3Transition
  93. NTSTATUS
  94. KdDebuggerInitialize0(
  95. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  96. )
  97. /*++
  98. Routine Description:
  99. This API allows the debugger DLL to parse the boot.ini strings and
  100. perform any initialization. It cannot be assumed that the entire NT
  101. kernel has been initialized at this time. Memory management services,
  102. for example, will not be available. After this call has returned, the
  103. debugger DLL may receive requests to send and receive packets.
  104. Arguments:
  105. LoaderBlock - Supplies a pointer to the loader parameter block
  106. Return Value:
  107. STATUS_SUCCESS, or error
  108. --*/
  109. {
  110. NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
  111. PCHAR Options;
  112. PCHAR BusParametersOption;
  113. PCHAR ChannelOption;
  114. PCHAR BusOption;
  115. PCI_SLOT_NUMBER slotNumber;
  116. PDEBUG_DEVICE_DESCRIPTOR DbgDeviceDescriptor = &Kd1394Parameters.DbgDeviceDescriptor;
  117. // first time is called with valid LoaderBlock
  118. if (LoaderBlock != NULL) {
  119. // set the debugger as inactive
  120. Kd1394Parameters.DebuggerActive = FALSE;
  121. if (LoaderBlock->LoadOptions != NULL) {
  122. Options = LoaderBlock->LoadOptions;
  123. _strupr(Options);
  124. // retrieve the channel number
  125. // CHANGE: this is actually an instance id and should be changed.
  126. ChannelOption = strstr(Options, CHANNEL_OPTION);
  127. if (ChannelOption) {
  128. ChannelOption += strlen(CHANNEL_OPTION);
  129. while (*ChannelOption == ' ') {
  130. ChannelOption++;
  131. }
  132. if (*ChannelOption != '\0') {
  133. Kd1394Parameters.Id = atol(ChannelOption + 1);
  134. }
  135. }
  136. else {
  137. // default to channel 0 - there should be no default???
  138. Kd1394Parameters.Id = 0;
  139. }
  140. // set vendor/class
  141. DbgDeviceDescriptor->VendorID = -1;
  142. DbgDeviceDescriptor->DeviceID = -1;
  143. DbgDeviceDescriptor->BaseClass = PCI_CLASS_SERIAL_BUS_CTLR;
  144. DbgDeviceDescriptor->SubClass = PCI_SUBCLASS_SB_IEEE1394;
  145. // support only ohci controllers
  146. DbgDeviceDescriptor->ProgIf = 0x10;
  147. DbgDeviceDescriptor->Bus = -1;
  148. DbgDeviceDescriptor->Slot = -1;
  149. // now find PCI addressing information
  150. BusParametersOption = strstr(Options, BUSPARAMETERS_OPTION);
  151. if (BusParametersOption) {
  152. do {
  153. BusParametersOption += strlen(BUSPARAMETERS_OPTION);
  154. while (*BusParametersOption == ' ') {
  155. BusParametersOption++;
  156. }
  157. // first get the pci bus number
  158. if ((*BusParametersOption != '\0')) {
  159. DbgDeviceDescriptor->Bus = atol(BusParametersOption+1);
  160. }
  161. else {
  162. break;
  163. }
  164. // now find the device number
  165. while ((*BusParametersOption != '.') && (*BusParametersOption != '\0')) {
  166. BusParametersOption++;
  167. }
  168. if ((*BusParametersOption != '\0')) {
  169. slotNumber.u.AsULONG = 0;
  170. slotNumber.u.bits.DeviceNumber = atol(++BusParametersOption);
  171. }
  172. else {
  173. break;
  174. }
  175. // now find the function number
  176. while ((*BusParametersOption != '.') && (*BusParametersOption != '\0')) {
  177. BusParametersOption++;
  178. }
  179. if ((*BusParametersOption != '\0')) {
  180. slotNumber.u.bits.FunctionNumber = atol(BusParametersOption+1);
  181. }
  182. else {
  183. break;
  184. }
  185. DbgDeviceDescriptor->Slot = slotNumber.u.AsULONG;
  186. } while (FALSE);
  187. }
  188. // see if the nobus flag is set
  189. BusOption = strstr(Options, BUS_OPTION);
  190. if (BusOption) {
  191. Kd1394Parameters.NoBus = TRUE;
  192. }
  193. else {
  194. Kd1394Parameters.NoBus = FALSE;
  195. }
  196. // find and configure the pci controller and do 1394 specific init
  197. if (Kd1394pInitialize(&Kd1394Parameters, LoaderBlock)) {
  198. Kd1394Parameters.DebuggerActive = TRUE;
  199. ntStatus = STATUS_SUCCESS;
  200. }
  201. }
  202. // hmmm...what happens if LoaderBlock->LoadOptions == NULL??
  203. }
  204. else {
  205. ntStatus = STATUS_SUCCESS;
  206. }
  207. return(ntStatus);
  208. } // KdDebuggerInitialize0
  209. NTSTATUS
  210. KdDebuggerInitialize1(
  211. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  212. )
  213. /*++
  214. Routine Description:
  215. This API allows the debugger DLL to do any initialization that it needs
  216. to do after the NT kernel services are available. Mm and registry APIs
  217. will be guaranteed to be available at this time. If the specific
  218. debugger DLL implementation uses a PCI device, it will set a registry
  219. key (discussed later) that notifies the PCI driver that a specific PCI
  220. device is being used for debugging.
  221. Arguments:
  222. LoaderBlock - Supplies a pointer to the loader parameter block
  223. Return Value:
  224. STATUS_SUCCESS, or appropriate error status
  225. --*/
  226. {
  227. WCHAR Buffer[16];
  228. OBJECT_ATTRIBUTES ObjectAttributes;
  229. UNICODE_STRING UnicodeString;
  230. HANDLE BaseHandle = NULL;
  231. HANDLE Handle = NULL;
  232. ULONG disposition, i;
  233. ULONG ulLength, ulResult;
  234. NTSTATUS ntStatus;
  235. PHYSICAL_ADDRESS physAddr;
  236. ULONG BusNumber;
  237. ULONG SlotNumber;
  238. PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
  239. // make sure we are active, if not, exit
  240. if (Kd1394Parameters.DebuggerActive == FALSE) {
  241. return(STATUS_UNSUCCESSFUL);
  242. }
  243. //
  244. // Open PCI Debug service key.
  245. //
  246. RtlInitUnicodeString( &UnicodeString,
  247. L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES\\PCI\\DEBUG"
  248. );
  249. InitializeObjectAttributes( &ObjectAttributes,
  250. &UnicodeString,
  251. OBJ_CASE_INSENSITIVE,
  252. NULL,
  253. (PSECURITY_DESCRIPTOR)NULL
  254. );
  255. ntStatus = ZwOpenKey(&BaseHandle, KEY_READ, &ObjectAttributes);
  256. if (!NT_SUCCESS(ntStatus)) {
  257. return(STATUS_SUCCESS);
  258. }
  259. for (i=0; i<MAX_DEBUGGING_DEVICES_SUPPORTED; i++) {
  260. swprintf(Buffer, L"%d", i);
  261. RtlInitUnicodeString(&UnicodeString, Buffer);
  262. InitializeObjectAttributes( &ObjectAttributes,
  263. &UnicodeString,
  264. OBJ_CASE_INSENSITIVE,
  265. BaseHandle,
  266. (PSECURITY_DESCRIPTOR)NULL
  267. );
  268. ntStatus = ZwOpenKey(&Handle, KEY_READ, &ObjectAttributes);
  269. if (NT_SUCCESS(ntStatus)) {
  270. ulLength = sizeof(KEY_VALUE_FULL_INFORMATION)+sizeof(ULONG);
  271. PartialInfo = ExAllocatePoolWithTag(NonPagedPool, ulLength, '31kd');
  272. if (PartialInfo == NULL) {
  273. ZwClose(Handle);
  274. continue;
  275. }
  276. RtlInitUnicodeString (&UnicodeString, L"Bus");
  277. ntStatus = ZwQueryValueKey( Handle,
  278. &UnicodeString,
  279. KeyValuePartialInformation,
  280. PartialInfo,
  281. ulLength,
  282. &ulResult
  283. );
  284. if (NT_SUCCESS(ntStatus)) {
  285. RtlCopyMemory(&BusNumber, &PartialInfo->Data, sizeof(ULONG));
  286. }
  287. RtlInitUnicodeString (&UnicodeString, L"Slot");
  288. ntStatus = ZwQueryValueKey( Handle,
  289. &UnicodeString,
  290. KeyValuePartialInformation,
  291. PartialInfo,
  292. ulLength,
  293. &ulResult
  294. );
  295. if (NT_SUCCESS(ntStatus)) {
  296. RtlCopyMemory(&SlotNumber, &PartialInfo->Data, sizeof(ULONG));
  297. }
  298. ExFreePool(PartialInfo);
  299. if ((Kd1394Parameters.DbgDeviceDescriptor.Bus == BusNumber) &&
  300. (Kd1394Parameters.DbgDeviceDescriptor.Slot == SlotNumber)) {
  301. // we found our instance, let's add our keys...
  302. physAddr = MmGetPhysicalAddress(&Kd1394Data->Config);
  303. RtlInitUnicodeString (&UnicodeString, L"DebugAddress");
  304. ntStatus = ZwSetValueKey( Handle,
  305. &UnicodeString,
  306. 0,
  307. REG_QWORD,
  308. &physAddr,
  309. sizeof(ULARGE_INTEGER)
  310. );
  311. RtlInitUnicodeString (&UnicodeString, L"NoBus");
  312. ntStatus = ZwSetValueKey( Handle,
  313. &UnicodeString,
  314. 0,
  315. REG_DWORD,
  316. &Kd1394Parameters.NoBus,
  317. sizeof(ULONG)
  318. );
  319. }
  320. ZwClose(Handle);
  321. }
  322. }
  323. ZwClose(BaseHandle);
  324. return(STATUS_SUCCESS);
  325. } // KdDebuggerInitialize1
  326. NTSTATUS
  327. KdSave(
  328. IN BOOLEAN KdSleepTransition
  329. )
  330. /*++
  331. Routine Description:
  332. The HAL calls this function as late as possible before putting the
  333. machine to sleep.
  334. Arguments:
  335. KdSleepTransition - TRUE when transitioning to/from sleep state
  336. Return Value:
  337. STATUS_SUCCESS, or appropriate error status
  338. --*/
  339. {
  340. return(STATUS_SUCCESS);
  341. } // KdSave
  342. NTSTATUS
  343. KdRestore(
  344. IN BOOLEAN KdSleepTransition
  345. )
  346. /*++
  347. Routine Description:
  348. The HAL calls this function as early as possible after resuming from a
  349. sleep state.
  350. Arguments:
  351. KdSleepTransition - TRUE when transitioning to/from sleep state
  352. Return Value:
  353. STATUS_SUCCESS, or appropriate error status
  354. --*/
  355. {
  356. return(STATUS_SUCCESS);
  357. } // KdRestore