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.

726 lines
14 KiB

  1. /*++
  2. Copyright (c) 1995,1996 Microsoft Corporation
  3. :ts=4
  4. Module Name:
  5. dbg.c
  6. Abstract:
  7. Debug Code for UHCD.
  8. Environment:
  9. kernel mode only
  10. Notes:
  11. Revision History:
  12. 10-08-95 : created
  13. --*/
  14. #include "wdm.h"
  15. #include "stdarg.h"
  16. #include "stdio.h"
  17. #include "usbdi.h"
  18. #include "hcdi.h"
  19. #include "uhcd.h"
  20. // debug compile defines
  21. // DEBUG# sets the level of spew 0 = none
  22. // > 2 turns on debug heap code
  23. // NTKERN_TRACE puts ' in the format buffer so that spew goes
  24. // to ntkern buffer
  25. #if DBG
  26. // This turns the looping assert so that testers can't hit g
  27. // past our assert before we can look at it.
  28. // Win9x testers tend to do this but NT testers are conditioned not
  29. // to so we only enable it for a DEBUG1 compile (win9x)
  30. ULONG UHCD_Debug_Asserts =
  31. #ifdef DEBUG1
  32. 1;
  33. #else
  34. 0;
  35. #endif
  36. // this flag causes us to write a ' in the format string
  37. // so that the string goes to the NTKERN buffer
  38. // this trick causes problems with driver verifier on NT
  39. // and the trace buffer isn't in NT anyway
  40. ULONG UHCD_W98_Debug_Trace =
  41. #ifdef NTKERN_TRACE
  42. 1;
  43. #else
  44. 0;
  45. #endif
  46. // set the debug output spew level based on the DEBUG# define
  47. // if compiled for W98 DEBUG1 is default
  48. // if compiled for NT zero should be default
  49. ULONG UHCD_Debug_Trace_Level =
  50. #ifdef DEBUG3
  51. #define DEBUG_HEAP
  52. 3;
  53. #else
  54. #ifdef DEBUG2
  55. 2;
  56. #else
  57. #ifdef DEBUG1
  58. 1;
  59. #else
  60. 0;
  61. #endif // DEBUG1
  62. #endif // DEBUG2
  63. #endif // DEBUG3
  64. LONG UHCD_TotalAllocatedHeapSpace = 0;
  65. ULONG
  66. _cdecl
  67. UHCD_KdPrintX(
  68. ULONG l,
  69. PCH Format,
  70. ...
  71. )
  72. {
  73. va_list list;
  74. int i;
  75. int arg[5];
  76. if (UHCD_Debug_Trace_Level >= l) {
  77. if (l <= 1) {
  78. // if flag is set override the '
  79. // so that the level 1 strings are
  80. // printed on the debugger terminal
  81. if (UHCD_W98_Debug_Trace) {
  82. DbgPrint("UHCD.SYS: ");
  83. *Format = ' ';
  84. } else {
  85. DbgPrint("'UHCD.SYS: ");
  86. }
  87. } else {
  88. DbgPrint("'UHCD.SYS: ");
  89. }
  90. va_start(list, Format);
  91. for (i=0; i<4; i++)
  92. arg[i] = va_arg(list, int);
  93. DbgPrint(Format, arg[0], arg[1], arg[2], arg[3]);
  94. }
  95. return 0;
  96. }
  97. #if 0
  98. ULONG
  99. UHCD_DebugCommand(
  100. IN ULONG Command,
  101. IN ULONG Paramater1
  102. )
  103. /*++
  104. Routine Description:
  105. This routine performs a specific debug function.
  106. Arguments:
  107. Command - debug function
  108. Return Value:
  109. STATUS_SUCCESS if successful,
  110. STATUS_UNSUCCESSFUL otherwise
  111. --*/
  112. {
  113. USBD_STATUS status = USBD_STATUS_SUCCESS;
  114. switch (Command) {
  115. // case DBG_DUMP_FRAME_LIST:
  116. break;
  117. default:
  118. status = USBD_STATUS_INVALID_PARAMETER;
  119. }
  120. return status;
  121. }
  122. #endif
  123. VOID
  124. UHCD_Debug_DumpTD(
  125. IN struct _HW_TRANSFER_DESCRIPTOR *Transfer
  126. )
  127. /*++
  128. Routine Description:
  129. Dump a transfer descriptor to the debug terminal
  130. Arguments:
  131. Return Value:
  132. --*/
  133. {
  134. if (UHCD_Debug_Trace_Level < 3)
  135. return;
  136. UHCD_KdPrint((2, "'TD DESCRIPTOR @va %0x\n", Transfer));
  137. UHCD_KdPrint((2, "'TD ActualLength %0x\n", Transfer->ActualLength));
  138. UHCD_KdPrint((2, "'TD Reserved_1 %0x\n", Transfer->Reserved_1));
  139. UHCD_KdPrint((2, "'TD Active %0x\n", Transfer->Active));
  140. UHCD_KdPrint((2, "'TD StatusField %0x\n", Transfer->StatusField));
  141. UHCD_KdPrint((2, "'TD InterruptOnComplete %0x\n", Transfer->InterruptOnComplete));
  142. UHCD_KdPrint((2, "'TD ShortPacketDetect %0x\n", Transfer->ShortPacketDetect));
  143. UHCD_KdPrint((2, "'TD Isochronous %0x\n", Transfer->Isochronous));
  144. UHCD_KdPrint((2, "'TD LowSpeedControl %0x\n", Transfer->LowSpeedControl));
  145. UHCD_KdPrint((2, "'TD ErrorCounter %0x\n", Transfer->ErrorCounter));
  146. UHCD_KdPrint((2, "'TD ReservedMBZ %0x\n", Transfer->ReservedMBZ));
  147. UHCD_KdPrint((2, "'TD PID %0x\n", Transfer->PID));
  148. UHCD_KdPrint((2, "'TD Address %0x\n", Transfer->Address));
  149. UHCD_KdPrint((2, "'TD Endpoint %0x\n", Transfer->Endpoint));
  150. UHCD_KdPrint((2, "'TD RetryToggle %0x\n", Transfer->RetryToggle));
  151. UHCD_KdPrint((2, "'TD Reserved_2 %0x\n", Transfer->Reserved_2));
  152. UHCD_KdPrint((2, "'TD MaxLength %0x\n", Transfer->MaxLength));
  153. }
  154. VOID
  155. UHCD_Assert(
  156. IN PVOID FailedAssertion,
  157. IN PVOID FileName,
  158. IN ULONG LineNumber,
  159. IN PCHAR Message
  160. )
  161. /*++
  162. Routine Description:
  163. Debug Assert function.
  164. Arguments:
  165. DeviceObject - pointer to a device object
  166. Irp - pointer to an I/O Request Packet
  167. Return Value:
  168. --*/
  169. {
  170. assert_loop:
  171. // just call the NT assert function and stop
  172. // in the debugger.
  173. RtlAssert( FailedAssertion, FileName, LineNumber, Message );
  174. // loop here to prevent users from going past
  175. // are assert before we can look at it
  176. // we only do thi sif the W98 DEBUG mode is set
  177. TRAP();
  178. if (UHCD_Debug_Asserts) {
  179. goto assert_loop;
  180. }
  181. return;
  182. }
  183. VOID
  184. UHCD_CheckSystemBuffer(
  185. IN PUCHAR VirtualAddress,
  186. IN ULONG Length
  187. )
  188. /*++
  189. Routine Description:
  190. Verify that this virtual address points to physically
  191. contiguous memory.
  192. Arguments:
  193. VirtualAddress - virtual address of the system buffer
  194. Length - length of buffer
  195. Return Value:
  196. --*/
  197. {
  198. UHCD_ASSERT(Length <= PAGE_SIZE);
  199. UHCD_ASSERT( ADDRESS_AND_SIZE_TO_SPAN_PAGES( VirtualAddress, Length ) <= 1 );
  200. }
  201. //
  202. // tag buffer we use to mark heap blocks we allocate
  203. //
  204. typedef struct _HEAP_TAG_BUFFER {
  205. ULONG Sig;
  206. ULONG Length;
  207. } HEAP_TAG_BUFFER, *PHEAP_TAG_BUFFER;
  208. PVOID
  209. UHCD_Debug_GetHeap(
  210. IN POOL_TYPE PoolType,
  211. IN ULONG NumberOfBytes,
  212. IN ULONG Signature,
  213. IN PLONG TotalAllocatedHeapSpace
  214. )
  215. /*++
  216. Routine Description:
  217. Debug routine, used to debug heap problems. We are using this since
  218. most NT debug functions are not supported by NTKERN.
  219. Arguments:
  220. PoolType - pool type passed to ExAllocatePool
  221. NumberOfBytes - number of bytes for item
  222. Signature - four byte signature supplied by caller
  223. TotalAllocatedHeapSpace - pointer to variable where client stores
  224. the total accumulated heap space allocated.
  225. Return Value:
  226. pointer to allocated memory
  227. --*/
  228. {
  229. PUCHAR p;
  230. #ifdef DEBUG_HEAP
  231. ULONG *stk;
  232. PHEAP_TAG_BUFFER tagBuffer;
  233. // we call ExAllocatePoolWithTag but no tag will be added
  234. // when running under NTKERN
  235. #ifdef _M_IX86
  236. _asm mov stk, ebp
  237. #endif
  238. p = (PUCHAR) ExAllocatePoolWithTag(PoolType,
  239. NumberOfBytes + sizeof(HEAP_TAG_BUFFER),
  240. Signature);
  241. if (p) {
  242. tagBuffer = (PHEAP_TAG_BUFFER) p;
  243. tagBuffer->Sig = Signature;
  244. tagBuffer->Length = NumberOfBytes;
  245. p += sizeof(HEAP_TAG_BUFFER);
  246. *TotalAllocatedHeapSpace += NumberOfBytes;
  247. }
  248. // LOGENTRY(LOG_MISC, (PUCHAR) &Signature, 0, 0, 0);
  249. // LOGENTRY(LOG_MISC, 'GetH', p, NumberOfBytes, stk[1] & 0x00FFFFFF);
  250. #else
  251. p = (PUCHAR) ExAllocatePoolWithTag(PoolType,
  252. NumberOfBytes,
  253. Signature);
  254. #endif /* DEBUG_HEAP */
  255. return p;
  256. }
  257. VOID
  258. UHCD_Debug_RetHeap(
  259. IN PVOID P,
  260. IN ULONG Signature,
  261. IN PLONG TotalAllocatedHeapSpace
  262. )
  263. /*++
  264. Routine Description:
  265. Debug routine, used to debug heap problems. We are using this since
  266. most NT debug functions are not supported by NTKERN.
  267. Arguments:
  268. P - pointer to free
  269. Return Value:
  270. none.
  271. --*/
  272. {
  273. #ifdef DEBUG_HEAP
  274. PHEAP_TAG_BUFFER tagBuffer;
  275. ULONG *stk;
  276. UHCD_ASSERT(P != 0);
  277. #ifdef _M_IX86
  278. _asm mov stk, ebp
  279. #endif
  280. tagBuffer = (PHEAP_TAG_BUFFER) ((PUCHAR)P - sizeof(HEAP_TAG_BUFFER));
  281. *TotalAllocatedHeapSpace -= tagBuffer->Length;
  282. // LOGENTRY(LOG_MISC, (PUCHAR) &Signature, 0, 0, 0);
  283. // LOGENTRY(LOG_MISC, 'RetH', P, tagBuffer->Length, stk[1] & 0x00FFFFFF);
  284. UHCD_ASSERT(*TotalAllocatedHeapSpace >= 0);
  285. UHCD_ASSERT(tagBuffer->Sig == Signature);
  286. // fill the buffer with bad data
  287. RtlFillMemory(P, tagBuffer->Length, 0xff);
  288. tagBuffer->Sig = UHCD_FREE_TAG;
  289. // free the original block
  290. ExFreePool(tagBuffer);
  291. #else
  292. ExFreePool(P);
  293. #endif /* DEBUG_HEAP */
  294. }
  295. #if DBG
  296. VOID
  297. UHCD_PrintPowerMessage(
  298. PUCHAR Label,
  299. UCHAR MinorFunction
  300. )
  301. /*++
  302. Routine Description:
  303. Arguments:
  304. Return Value:
  305. NT status code
  306. --*/
  307. {
  308. UHCD_KdPrint((2, "'(%s) ", Label));
  309. switch (MinorFunction) {
  310. case IRP_MN_WAIT_WAKE:
  311. UHCD_KdPrint((2, "'IRP_MN_WAIT_WAKE\n"));
  312. break;
  313. case IRP_MN_SET_POWER:
  314. UHCD_KdPrint((2, "'IRP_MN_SET_POWER\n"));
  315. break;
  316. case IRP_MN_QUERY_POWER:
  317. UHCD_KdPrint((2, "'IRP_MN_QUERY_POWER\n"));
  318. break;
  319. }
  320. }
  321. VOID
  322. UHCD_PrintPnPMessage(
  323. PUCHAR Label,
  324. UCHAR MinorFunction
  325. )
  326. /*++
  327. Routine Description:
  328. Arguments:
  329. Return Value:
  330. NT status code
  331. --*/
  332. {
  333. UHCD_KdPrint((2, "'(%s) ", Label));
  334. switch (MinorFunction) {
  335. case IRP_MN_START_DEVICE:
  336. UHCD_KdPrint((2, "'IRP_MN_START_DEVICE\n"));
  337. break;
  338. case IRP_MN_STOP_DEVICE:
  339. UHCD_KdPrint((2, "'IRP_MN_STOP_DEVICE\n"));
  340. break;
  341. case IRP_MN_REMOVE_DEVICE:
  342. UHCD_KdPrint((2, "'IRP_MN_REMOVE_DEVICE\n"));
  343. break;
  344. case IRP_MN_QUERY_STOP_DEVICE:
  345. UHCD_KdPrint((2, "'IRP_MN_QUERY_STOP_DEVICE\n"));
  346. break;
  347. case IRP_MN_CANCEL_STOP_DEVICE:
  348. UHCD_KdPrint((2, "'IRP_MN_CANCEL_STOP_DEVICE\n"));
  349. break;
  350. case IRP_MN_QUERY_REMOVE_DEVICE:
  351. UHCD_KdPrint((2, "'IRP_MN_QUERY_REMOVE_DEVICE\n"));
  352. break;
  353. case IRP_MN_CANCEL_REMOVE_DEVICE:
  354. UHCD_KdPrint((2, "'IRP_MN_CANCEL_REMOVE_DEVICE\n"));
  355. break;
  356. }
  357. }
  358. #endif
  359. #endif /* DBG */
  360. #ifdef DEBUG_LOG
  361. KSPIN_LOCK LogSpinLock;
  362. struct UHCD_LOG_ENTRY {
  363. ULONG le_sig; // Identifying string
  364. ULONG_PTR le_info1; // entry specific info
  365. ULONG_PTR le_info2; // entry specific info
  366. ULONG_PTR le_info3; // entry specific info
  367. }; /* USBD_LOG_ENTRY */
  368. struct UHCD_LOG_ENTRY *HcdLStart = 0; // No log yet
  369. struct UHCD_LOG_ENTRY *HcdLPtr;
  370. struct UHCD_LOG_ENTRY *HcdLEnd;
  371. #ifdef PROFILE
  372. ULONG LogMask = LOG_PROFILE;
  373. #else
  374. ULONG LogMask = 0xFFFFFFFF;
  375. #endif
  376. VOID
  377. UHCD_Debug_LogEntry(
  378. IN ULONG Mask,
  379. IN ULONG Sig,
  380. IN ULONG_PTR Info1,
  381. IN ULONG_PTR Info2,
  382. IN ULONG_PTR Info3
  383. )
  384. /*++
  385. Routine Description:
  386. Adds an Entry to UHCD log.
  387. Arguments:
  388. Return Value:
  389. None.
  390. --*/
  391. {
  392. KIRQL irql;
  393. typedef union _SIG {
  394. struct {
  395. UCHAR Byte0;
  396. UCHAR Byte1;
  397. UCHAR Byte2;
  398. UCHAR Byte3;
  399. } b;
  400. ULONG l;
  401. } SIG, *PSIG;
  402. SIG sig, rsig;
  403. if (HcdLStart == 0) {
  404. return;
  405. }
  406. if ((Mask & LogMask) == 0) {
  407. return;
  408. }
  409. irql = KeGetCurrentIrql();
  410. if (irql < DISPATCH_LEVEL) {
  411. KeAcquireSpinLock(&LogSpinLock, &irql);
  412. } else {
  413. KeAcquireSpinLockAtDpcLevel(&LogSpinLock);
  414. }
  415. if (HcdLPtr > HcdLStart) {
  416. HcdLPtr -= 1; // Decrement to next entry
  417. } else {
  418. HcdLPtr = HcdLEnd;
  419. }
  420. //RtlCopyMemory(HcdLPtr->le_name, Name, 4);
  421. // LPtr->le_ret = (stk[1] & 0x00ffffff) | (CurVMID()<<24);
  422. sig.l = Sig;
  423. rsig.b.Byte0 = sig.b.Byte3;
  424. rsig.b.Byte1 = sig.b.Byte2;
  425. rsig.b.Byte2 = sig.b.Byte1;
  426. rsig.b.Byte3 = sig.b.Byte0;
  427. HcdLPtr->le_sig = rsig.l;
  428. HcdLPtr->le_info1 = Info1;
  429. HcdLPtr->le_info2 = Info2;
  430. HcdLPtr->le_info3 = Info3;
  431. UHCD_ASSERT(HcdLPtr >= HcdLStart);
  432. if (irql < DISPATCH_LEVEL) {
  433. KeReleaseSpinLock(&LogSpinLock, irql);
  434. } else {
  435. KeReleaseSpinLockFromDpcLevel(&LogSpinLock);
  436. }
  437. return;
  438. }
  439. VOID
  440. UHCD_LogInit(
  441. )
  442. /*++
  443. Routine Description:
  444. Init the debug log - remember interesting information in a circular buffer
  445. Arguments:
  446. Return Value:
  447. None.
  448. --*/
  449. {
  450. #ifdef MAX_DEBUG
  451. ULONG logSize = 4096*6;
  452. #else
  453. ULONG logSize = 4096*3;
  454. #endif
  455. KeInitializeSpinLock(&LogSpinLock);
  456. HcdLStart = ExAllocatePoolWithTag(NonPagedPool,
  457. logSize,
  458. UHCD_TAG);
  459. if (HcdLStart) {
  460. HcdLPtr = HcdLStart;
  461. // Point the end (and first entry) 1 entry from the end of the segment
  462. HcdLEnd = HcdLStart + (logSize / sizeof(struct UHCD_LOG_ENTRY)) - 1;
  463. } else {
  464. TRAP();
  465. }
  466. return;
  467. }
  468. VOID
  469. UHCD_LogFree(
  470. )
  471. /*++
  472. Routine Description:
  473. Arguments:
  474. Return Value:
  475. None.
  476. --*/
  477. {
  478. if (HcdLStart) {
  479. ExFreePool(HcdLStart);
  480. }
  481. return;
  482. }
  483. VOID
  484. UHCD_LogTD(
  485. IN ULONG s,
  486. IN PULONG p
  487. )
  488. {
  489. LOGENTRY(LOG_MISC, s, p, 0, 0);
  490. LOGENTRY(LOG_MISC, s, *p, *(p+1), *(p+2));
  491. LOGENTRY(LOG_MISC, s, *(p+3), *(p+4), *(p+5));
  492. }
  493. #ifdef DEBUG_LOG_IO
  494. #undef WRITE_PORT_USHORT
  495. #undef WRITE_PORT_ULONG
  496. #undef WRITE_PORT_UCHAR
  497. #undef READ_PORT_USHORT
  498. #undef READ_PORT_ULONG
  499. #undef READ_PORT_UCHAR
  500. USHORT
  501. UhcdLogIoUshort(PUSHORT Port, USHORT Val, BOOLEAN Write)
  502. {
  503. USHORT rval = 0;
  504. if (Write) {
  505. LOGENTRY(LOG_IO, 'WrUS', Port, (ULONG_PTR)Val & 0x0000ffff, 0);
  506. WRITE_PORT_USHORT(Port, Val);
  507. } else {
  508. rval = READ_PORT_USHORT(Port);
  509. LOGENTRY(LOG_IO, 'RdUS', Port, (ULONG_PTR)rval & 0x0000ffff, 0);
  510. }
  511. return rval;
  512. }
  513. ULONG
  514. UhcdLogIoUlong(PULONG Port, ULONG Val, BOOLEAN Write)
  515. {
  516. ULONG rval = 0;
  517. if (Write) {
  518. LOGENTRY(LOG_IO, 'WrUL', Port, Val, 0);
  519. WRITE_PORT_ULONG(Port, Val);
  520. } else {
  521. rval = READ_PORT_ULONG(Port);
  522. LOGENTRY(LOG_IO, 'RdUL', Port, rval, 0);
  523. }
  524. return rval;
  525. }
  526. UCHAR
  527. UhcdLogIoUchar(PUCHAR Port, UCHAR Val, BOOLEAN Write)
  528. {
  529. UCHAR rval = 0;
  530. if (Write) {
  531. LOGENTRY(LOG_IO, 'WrUC', Port, (ULONG_PTR)Val & 0x000000ff, 0);
  532. WRITE_PORT_UCHAR(Port, Val);
  533. } else {
  534. rval = READ_PORT_UCHAR(Port);
  535. LOGENTRY(LOG_IO, 'RdUC', Port, (ULONG_PTR)rval & 0x000000ff, 0);
  536. }
  537. return rval;
  538. }
  539. #endif // DEBUG_LOG_IO
  540. #endif /* DEBUG_LOG */