Leaked source code of windows server 2003
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.

325 lines
7.5 KiB

  1. /*++
  2. Copyright (c) 1996-2000 Microsoft Corporation
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. This module contains assorted utility functions for PCI.SYS.
  7. Author:
  8. Peter Johnston (peterj) 20-Nov-1996
  9. Revision History:
  10. Eric Nelson (enelson) 20-Mar-2000 - kidnap registry function
  11. --*/
  12. #include "agplib.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(PAGE, AgpOpenKey)
  15. #pragma alloc_text(PAGE, AgpStringToUSHORT)
  16. #endif
  17. ULONGLONG
  18. AgpGetDeviceFlags(
  19. IN PAGP_HACK_TABLE_ENTRY AgpHackTable,
  20. IN USHORT VendorID,
  21. IN USHORT DeviceID,
  22. IN USHORT SubVendorID,
  23. IN USHORT SubSystemID,
  24. IN UCHAR RevisionID
  25. )
  26. /*++
  27. Description:
  28. Look in the registry for any flags for this VendorId/DeviceId.
  29. Arguments:
  30. VendorId PCI Vendor ID (16 bits) of the manufacturer of the
  31. device.
  32. DeviceId PCI Device ID (16 bits) of the device.
  33. SubVendorID PCI SubVendorID representing the manufacturer of the
  34. subsystem
  35. SubSystemID PCI SubSystemID representing subsystem
  36. RevisionID PCI Revision denoting the revision of the device
  37. Return Value:
  38. 64 bit flags value or 0 if not found.
  39. --*/
  40. {
  41. PAGP_HACK_TABLE_ENTRY current;
  42. ULONGLONG hackFlags = 0;
  43. ULONG match, bestMatch = 0;
  44. if (AgpHackTable == NULL) {
  45. return hackFlags;
  46. }
  47. //
  48. // We want to do a best-case match:
  49. // VVVVDDDDSSSSssssRR
  50. // VVVVDDDDSSSSssss
  51. // VVVVDDDDRR
  52. // VVVVDDDD
  53. //
  54. // List is currently unsorted, so keep updating current best match.
  55. //
  56. for (current = AgpHackTable; current->VendorID != 0xFFFF; current++) {
  57. match = 0;
  58. //
  59. // Must at least match vendor/dev
  60. //
  61. if ((current->DeviceID != DeviceID) ||
  62. (current->VendorID != VendorID)) {
  63. continue;
  64. }
  65. match = 1;
  66. //
  67. // If this entry specifies a revision, check that it is consistent.
  68. //
  69. if (current->Flags & AGP_HACK_FLAG_REVISION) {
  70. if (current->RevisionID == RevisionID) {
  71. match += 2;
  72. } else {
  73. continue;
  74. }
  75. }
  76. //
  77. // If this entry specifies subsystems, check that they are consistent
  78. //
  79. if (current->Flags & AGP_HACK_FLAG_SUBSYSTEM) {
  80. if (current->SubVendorID == SubVendorID &&
  81. current->SubSystemID == SubSystemID) {
  82. match += 4;
  83. } else {
  84. continue;
  85. }
  86. }
  87. if (match > bestMatch) {
  88. bestMatch = match;
  89. hackFlags = current->DeviceFlags;
  90. }
  91. }
  92. return hackFlags;
  93. }
  94. BOOLEAN
  95. AgpOpenKey(
  96. IN PWSTR KeyName,
  97. IN HANDLE ParentHandle,
  98. OUT PHANDLE Handle,
  99. OUT PNTSTATUS Status
  100. )
  101. /*++
  102. Description:
  103. Open a registry key.
  104. Arguments:
  105. KeyName Name of the key to be opened.
  106. ParentHandle Pointer to the parent handle (OPTIONAL)
  107. Handle Pointer to a handle to recieve the opened key.
  108. Return Value:
  109. TRUE is key successfully opened, FALSE otherwise.
  110. --*/
  111. {
  112. UNICODE_STRING nameString;
  113. OBJECT_ATTRIBUTES nameAttributes;
  114. NTSTATUS localStatus;
  115. PAGED_CODE();
  116. RtlInitUnicodeString(&nameString, KeyName);
  117. InitializeObjectAttributes(&nameAttributes,
  118. &nameString,
  119. OBJ_CASE_INSENSITIVE,
  120. ParentHandle,
  121. (PSECURITY_DESCRIPTOR)NULL
  122. );
  123. localStatus = ZwOpenKey(Handle,
  124. KEY_READ,
  125. &nameAttributes
  126. );
  127. if (Status != NULL) {
  128. //
  129. // Caller wants underlying status.
  130. //
  131. *Status = localStatus;
  132. }
  133. //
  134. // Return status converted to a boolean, TRUE if
  135. // successful.
  136. //
  137. return NT_SUCCESS(localStatus);
  138. }
  139. BOOLEAN
  140. AgpStringToUSHORT(
  141. IN PWCHAR String,
  142. OUT PUSHORT Result
  143. )
  144. /*++
  145. Description:
  146. Takes a 4 character hexidecimal sting and converts it into a USHORT.
  147. Arguments:
  148. String - the string
  149. Result - the USHORT
  150. Return Value:
  151. TRUE is success, FASLE otherwise
  152. --*/
  153. {
  154. ULONG count;
  155. USHORT number = 0;
  156. PWCHAR current;
  157. current = String;
  158. for (count = 0; count < 4; count++) {
  159. number <<= 4;
  160. if (*current >= L'0' && *current <= L'9') {
  161. number |= *current - L'0';
  162. } else if (*current >= L'A' && *current <= L'F') {
  163. number |= *current + 10 - L'A';
  164. } else if (*current >= L'a' && *current <= L'f') {
  165. number |= *current + 10 - L'a';
  166. } else {
  167. return FALSE;
  168. }
  169. current++;
  170. }
  171. *Result = number;
  172. return TRUE;
  173. }
  174. ULONG_PTR
  175. AgpExecuteCriticalSystemRoutine(
  176. IN ULONG_PTR Context
  177. )
  178. /*++
  179. Routine Description:
  180. This routine is called in the context of KeIpiGenericCall, which
  181. executes it on all processors. It is used to execute
  182. a critical routine which needs all processors synchronized, such
  183. as probing the BARs of a device that could not otherwise be turned off.
  184. Only one context parameter is allowed in this routine, so it must
  185. contain both the routine to execute and any context that routine
  186. requires.
  187. When this routine is entered, it is guaranteed that all processors will
  188. already have been targeted with an IPI, and will be running at IPI_LEVEL.
  189. All processors will either be running this routine, or will be about to
  190. enter the routine. No arbitrary threads can possibly be running. No
  191. devices can interrupt the execution of this routine, since IPI_LEVEL is
  192. above all device IRQLs.
  193. Because this routine runs at IPI_LEVEL, no debug prints, asserts or other
  194. debugging can occur in this function without hanging MP machines.
  195. Arguments:
  196. Context - the context passed into the call to KeIpiGenericCall.
  197. It contains the critical routine to execute, any context required
  198. in that routine and a gate and a barrier to ensure that the critical
  199. routine is executed on only one processor, even though this function
  200. is executed on all processors.
  201. Return Value:
  202. STATUS_SUCCESS, or error
  203. --*/
  204. {
  205. NTSTATUS Status;
  206. PAGP_CRITICAL_ROUTINE_CONTEXT routineContext =
  207. (PAGP_CRITICAL_ROUTINE_CONTEXT)Context;
  208. Status = STATUS_SUCCESS;
  209. //
  210. // The Gate parameter in the routineContext is preinitialized
  211. // to 1, meaning that the first processor to reach this point
  212. // in the routine will decrement it to 0, and succeed the if
  213. // statement.
  214. //
  215. if (InterlockedDecrement(&routineContext->Gate) == 0) {
  216. //
  217. // This is only executed on one processor.
  218. //
  219. Status = (NTSTATUS)routineContext->Routine(routineContext->Extension,
  220. routineContext->Context
  221. );
  222. //
  223. // Free other processors.
  224. //
  225. routineContext->Barrier = 0;
  226. } else {
  227. //
  228. // Wait for gated function to complete.
  229. //
  230. do {
  231. } while (routineContext->Barrier != 0);
  232. }
  233. return Status;
  234. }