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.

1227 lines
31 KiB

  1. #include "precomp.h" // Precompiled header
  2. /****************************************************************************************
  3. * *
  4. * Module: SPX_UTILS.C *
  5. * *
  6. * Creation: 15th October 1998 *
  7. * *
  8. * Author: Paul Smith *
  9. * *
  10. * Version: 1.0.0 *
  11. * *
  12. * Description: Utility functions. *
  13. * *
  14. ****************************************************************************************/
  15. #define FILE_ID SPX_UTILS_C // File ID for Event Logging see SPX_DEFS.H for values.
  16. // Paging...
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text (PAGE, Spx_InitMultiString)
  19. #pragma alloc_text (PAGE, Spx_GetRegistryKeyValue)
  20. #pragma alloc_text (PAGE, Spx_PutRegistryKeyValue)
  21. #pragma alloc_text (PAGE, Spx_LogMessage)
  22. #pragma alloc_text (PAGE, Spx_LogError)
  23. #pragma alloc_text (PAGE, Spx_MemCompare)
  24. #endif
  25. /////////////////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Description:
  28. //
  29. // This routine will take a null terminated list of ascii strings and combine
  30. // them together to generate a unicode multi-string block
  31. //
  32. // Arguments:
  33. //
  34. // Multi - TRUE if a MULTI_SZ list is required, FALSE for a simple UNICODE
  35. //
  36. // MultiString - a unicode structure in which a multi-string will be built
  37. // ... - a null terminated list of narrow strings which will be
  38. // combined together. This list must contain at least a trailing NULL
  39. //
  40. // Return Value:
  41. //
  42. // NTSTATUS
  43. //
  44. /////////////////////////////////////////////////////////////////////////////////////////
  45. NTSTATUS
  46. Spx_InitMultiString(BOOLEAN multi, PUNICODE_STRING MultiString, ...)
  47. {
  48. ANSI_STRING ansiString;
  49. NTSTATUS status;
  50. PCSTR rawString;
  51. PWSTR unicodeLocation;
  52. ULONG multiLength = 0;
  53. UNICODE_STRING unicodeString;
  54. va_list ap;
  55. ULONG i;
  56. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  57. va_start(ap,MultiString);
  58. // Make sure that we won't leak memory
  59. ASSERT(MultiString->Buffer == NULL);
  60. rawString = va_arg(ap, PCSTR);
  61. while (rawString != NULL)
  62. {
  63. RtlInitAnsiString(&ansiString, rawString);
  64. multiLength += RtlAnsiStringToUnicodeSize(&(ansiString));
  65. rawString = va_arg(ap, PCSTR);
  66. }
  67. va_end( ap );
  68. if (multiLength == 0)
  69. {
  70. // Done
  71. RtlInitUnicodeString(MultiString, NULL);
  72. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Leaving Spx_InitMultiString (1)\n", PRODUCT_NAME));
  73. return STATUS_SUCCESS;
  74. }
  75. if(multi)
  76. multiLength += sizeof(WCHAR); // We need an extra null if we want a MULTI_SZ list
  77. MultiString->MaximumLength = (USHORT)multiLength;
  78. MultiString->Buffer = SpxAllocateMem(PagedPool, multiLength);
  79. MultiString->Length = 0;
  80. if (MultiString->Buffer == NULL)
  81. {
  82. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Leaving Spx_InitMultiString (2) - FAILURE\n", PRODUCT_NAME));
  83. return STATUS_INSUFFICIENT_RESOURCES;
  84. }
  85. SpxDbgMsg(SPX_MISC_DBG, ("%s: Allocated %lu bytes for buffer\n", PRODUCT_NAME, multiLength));
  86. #if DBG
  87. RtlFillMemory(MultiString->Buffer, multiLength, 0xff);
  88. #endif
  89. unicodeString.Buffer = MultiString->Buffer;
  90. unicodeString.MaximumLength = (USHORT) multiLength;
  91. va_start(ap, MultiString);
  92. rawString = va_arg(ap, PCSTR);
  93. while (rawString != NULL)
  94. {
  95. RtlInitAnsiString(&ansiString,rawString);
  96. status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, FALSE);
  97. // We don't allocate memory, so if something goes wrong here,
  98. // its the function that's at fault
  99. ASSERT(SPX_SUCCESS(status));
  100. // Check for any commas and replace them with NULLs
  101. ASSERT(unicodeString.Length % sizeof(WCHAR) == 0);
  102. for (i = 0; i < (unicodeString.Length / sizeof(WCHAR)); i++)
  103. {
  104. if (unicodeString.Buffer[i] == L'\x2C' || unicodeString.Buffer[i] == L'\x0C' )
  105. {
  106. unicodeString.Buffer[i] = L'\0';
  107. }
  108. }
  109. SpxDbgMsg(SPX_MISC_DBG, ("%s: unicode buffer: %ws\n", PRODUCT_NAME, unicodeString.Buffer));
  110. // Move the buffers along
  111. unicodeString.Buffer += ((unicodeString.Length / sizeof(WCHAR)) + 1);
  112. unicodeString.MaximumLength -= (unicodeString.Length + sizeof(WCHAR));
  113. unicodeString.Length = 0;
  114. // Next
  115. rawString = va_arg(ap, PCSTR);
  116. } // while
  117. va_end(ap);
  118. if(multi)
  119. {
  120. ASSERT(unicodeString.MaximumLength == sizeof(WCHAR));
  121. }
  122. else
  123. {
  124. ASSERT(unicodeString.MaximumLength == 0);
  125. }
  126. // Stick the final null there
  127. SpxDbgMsg(SPX_MISC_DBG, ("%s: unicode buffer last addr: 0x%X\n", PRODUCT_NAME, unicodeString.Buffer));
  128. if(multi)
  129. unicodeString.Buffer[0] = L'\0'; // We need an extra null if we want a MULTI_SZ list
  130. MultiString->Length = (USHORT)multiLength - sizeof(WCHAR);
  131. MultiString->MaximumLength = (USHORT)multiLength;
  132. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Leaving Spx_InitMultiString (3) - SUCCESS\n", PRODUCT_NAME));
  133. return STATUS_SUCCESS;
  134. }
  135. /////////////////////////////////////////////////////////////////////////////////////////
  136. //
  137. // Routine Description:
  138. // Reads a registry key value from an already opened registry key.
  139. //
  140. // Arguments:
  141. //
  142. // Handle Handle to the opened registry key
  143. //
  144. // KeyNameString ANSI string to the desired key
  145. //
  146. // KeyNameStringLength Length of the KeyNameString
  147. //
  148. // Data Buffer to place the key value in
  149. //
  150. // DataLength Length of the data buffer
  151. //
  152. // Return Value:
  153. //
  154. // STATUS_SUCCESS if all works, otherwise status of system call that
  155. // went wrong.
  156. //
  157. /////////////////////////////////////////////////////////////////////////////////////////
  158. NTSTATUS
  159. Spx_GetRegistryKeyValue(
  160. IN HANDLE Handle,
  161. IN PWCHAR KeyNameString,
  162. IN ULONG KeyNameStringLength,
  163. IN PVOID Data,
  164. IN ULONG DataLength
  165. )
  166. {
  167. UNICODE_STRING keyName;
  168. ULONG length;
  169. PKEY_VALUE_FULL_INFORMATION fullInfo;
  170. NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES;
  171. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  172. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Enter Spx_GetRegistryKeyValue\n", PRODUCT_NAME));
  173. RtlInitUnicodeString (&keyName, KeyNameString);
  174. length = sizeof(KEY_VALUE_FULL_INFORMATION) + KeyNameStringLength + DataLength;
  175. fullInfo = SpxAllocateMem(PagedPool, length);
  176. if(fullInfo)
  177. {
  178. status = ZwQueryValueKey( Handle,
  179. &keyName,
  180. KeyValueFullInformation,
  181. fullInfo,
  182. length,
  183. &length);
  184. if(SPX_SUCCESS(status))
  185. {
  186. // If there is enough room in the data buffer, copy the output
  187. if(DataLength >= fullInfo->DataLength)
  188. RtlCopyMemory (Data, ((PUCHAR) fullInfo) + fullInfo->DataOffset, fullInfo->DataLength);
  189. }
  190. SpxFreeMem(fullInfo);
  191. }
  192. return status;
  193. }
  194. /////////////////////////////////////////////////////////////////////////////////////////
  195. //
  196. // Routine Description:
  197. //
  198. // Writes a registry key value to an already opened registry key.
  199. //
  200. // Arguments:
  201. //
  202. // Handle Handle to the opened registry key
  203. //
  204. // PKeyNameString ANSI string to the desired key
  205. //
  206. // KeyNameStringLength Length of the KeyNameString
  207. //
  208. // Dtype REG_XYZ value type
  209. //
  210. // PData Buffer to place the key value in
  211. //
  212. // DataLength Length of the data buffer
  213. //
  214. // Return Value:
  215. //
  216. // STATUS_SUCCESS if all works, otherwise status of system call that
  217. // went wrong.
  218. //
  219. /////////////////////////////////////////////////////////////////////////////////////////
  220. NTSTATUS
  221. Spx_PutRegistryKeyValue(
  222. IN HANDLE Handle,
  223. IN PWCHAR PKeyNameString,
  224. IN ULONG KeyNameStringLength,
  225. IN ULONG Dtype,
  226. IN PVOID PData,
  227. IN ULONG DataLength
  228. )
  229. {
  230. NTSTATUS status;
  231. UNICODE_STRING keyname;
  232. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  233. SpxDbgMsg(SPX_TRACE_CALLS,("%s: Enter Spx_PutRegistryKeyValue\n", PRODUCT_NAME));
  234. RtlInitUnicodeString(&keyname, NULL);
  235. keyname.MaximumLength = (USHORT)(KeyNameStringLength + sizeof(WCHAR));
  236. keyname.Buffer = SpxAllocateMem(PagedPool, keyname.MaximumLength);
  237. if(keyname.Buffer == NULL)
  238. return STATUS_INSUFFICIENT_RESOURCES;
  239. RtlAppendUnicodeToString(&keyname, PKeyNameString);
  240. status = ZwSetValueKey(Handle, &keyname, 0, Dtype, PData, DataLength);
  241. SpxFreeMem(keyname.Buffer);
  242. return status;
  243. }
  244. VOID
  245. Spx_LogMessage(
  246. IN ULONG MessageSeverity,
  247. IN PDRIVER_OBJECT DriverObject,
  248. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  249. IN PHYSICAL_ADDRESS P1,
  250. IN PHYSICAL_ADDRESS P2,
  251. IN ULONG SequenceNumber,
  252. IN UCHAR MajorFunctionCode,
  253. IN UCHAR RetryCount,
  254. IN ULONG UniqueErrorValue,
  255. IN NTSTATUS FinalStatus,
  256. IN PCHAR szTemp) // Limited to 51 characters + 1 null
  257. {
  258. UNICODE_STRING ErrorMsg;
  259. ErrorMsg.Length = 0;
  260. ErrorMsg.Buffer = 0;
  261. Spx_InitMultiString(FALSE, &ErrorMsg, szTemp, NULL);
  262. switch(MessageSeverity)
  263. {
  264. case STATUS_SEVERITY_SUCCESS:
  265. Spx_LogError( DriverObject, // Driver Object
  266. DeviceObject, // Device Object (Optional)
  267. P1, // Physical Address 1
  268. P2, // Physical Address 2
  269. SequenceNumber, // SequenceNumber
  270. MajorFunctionCode, // Major Function Code
  271. RetryCount, // RetryCount
  272. UniqueErrorValue, // UniqueErrorValue
  273. FinalStatus, // FinalStatus
  274. SPX_SEVERITY_SUCCESS, // SpecificIOStatus
  275. ErrorMsg.Length + sizeof(WCHAR), // LengthOfInsert1
  276. ErrorMsg.Buffer, // Insert1
  277. 0, // LengthOfInsert2
  278. NULL); // Insert2
  279. break;
  280. case STATUS_SEVERITY_INFORMATIONAL:
  281. Spx_LogError( DriverObject, // Driver Object
  282. DeviceObject, // Device Object (Optional)
  283. P1, // Physical Address 1
  284. P2, // Physical Address 2
  285. SequenceNumber, // SequenceNumber
  286. MajorFunctionCode, // Major Function Code
  287. RetryCount, // RetryCount
  288. UniqueErrorValue, // UniqueErrorValue
  289. FinalStatus, // FinalStatus
  290. SPX_SEVERITY_INFORMATIONAL, // SpecificIOStatus
  291. ErrorMsg.Length + sizeof(WCHAR), // LengthOfInsert1
  292. ErrorMsg.Buffer, // Insert1
  293. 0, // LengthOfInsert2
  294. NULL); // Insert2
  295. break;
  296. case STATUS_SEVERITY_WARNING:
  297. Spx_LogError( DriverObject, // Driver Object
  298. DeviceObject, // Device Object (Optional)
  299. P1, // Physical Address 1
  300. P2, // Physical Address 2
  301. SequenceNumber, // SequenceNumber
  302. MajorFunctionCode, // Major Function Code
  303. RetryCount, // RetryCount
  304. UniqueErrorValue, // UniqueErrorValue
  305. FinalStatus, // FinalStatus
  306. SPX_SEVERITY_WARNING, // SpecificIOStatus
  307. ErrorMsg.Length + sizeof(WCHAR), // LengthOfInsert1
  308. ErrorMsg.Buffer, // Insert1
  309. 0, // LengthOfInsert2
  310. NULL); // Insert2
  311. break;
  312. case STATUS_SEVERITY_ERROR:
  313. default:
  314. Spx_LogError( DriverObject, // Driver Object
  315. DeviceObject, // Device Object (Optional)
  316. P1, // Physical Address 1
  317. P2, // Physical Address 2
  318. SequenceNumber, // SequenceNumber
  319. MajorFunctionCode, // Major Function Code
  320. RetryCount, // RetryCount
  321. UniqueErrorValue, // UniqueErrorValue
  322. FinalStatus, // FinalStatus
  323. SPX_SEVERITY_ERROR, // SpecificIOStatus
  324. ErrorMsg.Length + sizeof(WCHAR), // LengthOfInsert1
  325. ErrorMsg.Buffer, // Insert1
  326. 0, // LengthOfInsert2
  327. NULL); // Insert2
  328. break;
  329. }
  330. if(ErrorMsg.Buffer != NULL)
  331. SpxFreeMem(ErrorMsg.Buffer);
  332. }
  333. /////////////////////////////////////////////////////////////////////////////////////////
  334. //
  335. // Spx_LogError
  336. //
  337. /////////////////////////////////////////////////////////////////////////////////////////
  338. /*
  339. Routine Description:
  340. This routine allocates an error log entry, copies the supplied data
  341. to it, and requests that it be written to the error log file.
  342. Arguments:
  343. DriverObject - A pointer to the driver object for the device.
  344. DeviceObject - A pointer to the device object associated with the
  345. device that had the error, early in initialization, one may not
  346. yet exist.
  347. P1,P2 - If phyical addresses for the controller ports involved
  348. with the error are available, put them through as dump data.
  349. SequenceNumber - A ulong value that is unique to an IRP over the
  350. life of the irp in this driver - 0 generally means an error not
  351. associated with an irp.
  352. MajorFunctionCode - If there is an error associated with the irp,
  353. this is the major function code of that irp.
  354. RetryCount - The number of times a particular operation has been retried.
  355. UniqueErrorValue - A unique long word that identifies the particular
  356. call to this function.
  357. FinalStatus - The final status given to the irp that was associated
  358. with this error. If this log entry is being made during one of
  359. the retries this value will be STATUS_SUCCESS.
  360. SpecificIOStatus - The IO status for a particular error.
  361. LengthOfInsert1 - The length in bytes (including the terminating NULL)
  362. of the first insertion string.
  363. Insert1 - The first insertion string.
  364. LengthOfInsert2 - The length in bytes (including the terminating NULL)
  365. of the second insertion string. NOTE, there must
  366. be a first insertion string for their to be
  367. a second insertion string.
  368. Insert2 - The second insertion string.
  369. Return Value: None.
  370. */
  371. VOID
  372. Spx_LogError(
  373. IN PDRIVER_OBJECT DriverObject,
  374. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  375. IN PHYSICAL_ADDRESS P1,
  376. IN PHYSICAL_ADDRESS P2,
  377. IN ULONG SequenceNumber,
  378. IN UCHAR MajorFunctionCode,
  379. IN UCHAR RetryCount,
  380. IN ULONG UniqueErrorValue,
  381. IN NTSTATUS FinalStatus,
  382. IN NTSTATUS SpecificIOStatus,
  383. IN ULONG LengthOfInsert1,
  384. IN PWCHAR Insert1,
  385. IN ULONG LengthOfInsert2,
  386. IN PWCHAR Insert2
  387. )
  388. {
  389. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  390. PVOID objectToUse;
  391. SHORT dumpToAllocate = 0;
  392. PUCHAR ptrToFirstInsert;
  393. PUCHAR ptrToSecondInsert;
  394. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  395. if(Insert1 == NULL)
  396. LengthOfInsert1 = 0;
  397. if(Insert2 == NULL)
  398. LengthOfInsert2 = 0;
  399. if(ARGUMENT_PRESENT(DeviceObject))
  400. objectToUse = DeviceObject;
  401. else
  402. objectToUse = DriverObject;
  403. if(Spx_MemCompare(P1, (ULONG)1, PhysicalZero, (ULONG)1 ) != AddressesAreEqual)
  404. {
  405. dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS);
  406. }
  407. if(Spx_MemCompare(P2, (ULONG)1, PhysicalZero, (ULONG)1 ) != AddressesAreEqual)
  408. {
  409. dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS);
  410. }
  411. ErrorLogEntry = IoAllocateErrorLogEntry(objectToUse,
  412. (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + dumpToAllocate
  413. + LengthOfInsert1 + LengthOfInsert2)
  414. );
  415. if(ErrorLogEntry != NULL)
  416. {
  417. ErrorLogEntry->ErrorCode = SpecificIOStatus;
  418. ErrorLogEntry->SequenceNumber = SequenceNumber;
  419. ErrorLogEntry->MajorFunctionCode = MajorFunctionCode;
  420. ErrorLogEntry->RetryCount = RetryCount;
  421. ErrorLogEntry->UniqueErrorValue = UniqueErrorValue;
  422. ErrorLogEntry->FinalStatus = FinalStatus;
  423. ErrorLogEntry->DumpDataSize = dumpToAllocate;
  424. if(dumpToAllocate)
  425. {
  426. RtlCopyMemory(&ErrorLogEntry->DumpData[0], &P1, sizeof(PHYSICAL_ADDRESS));
  427. if(dumpToAllocate > sizeof(PHYSICAL_ADDRESS))
  428. {
  429. RtlCopyMemory( ((PUCHAR)&ErrorLogEntry->DumpData[0]) + sizeof(PHYSICAL_ADDRESS),
  430. &P2,
  431. sizeof(PHYSICAL_ADDRESS)
  432. );
  433. ptrToFirstInsert = ((PUCHAR)&ErrorLogEntry->DumpData[0]) + (2*sizeof(PHYSICAL_ADDRESS));
  434. }
  435. else
  436. {
  437. ptrToFirstInsert = ((PUCHAR)&ErrorLogEntry->DumpData[0]) + sizeof(PHYSICAL_ADDRESS);
  438. }
  439. }
  440. else
  441. {
  442. ptrToFirstInsert = (PUCHAR)&ErrorLogEntry->DumpData[0];
  443. }
  444. ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1;
  445. if(LengthOfInsert1)
  446. {
  447. ErrorLogEntry->NumberOfStrings = 1;
  448. ErrorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert - (PUCHAR)ErrorLogEntry);
  449. RtlCopyMemory(ptrToFirstInsert, Insert1, LengthOfInsert1);
  450. if(LengthOfInsert2)
  451. {
  452. ErrorLogEntry->NumberOfStrings = 2;
  453. RtlCopyMemory(ptrToSecondInsert, Insert2, LengthOfInsert2);
  454. }
  455. }
  456. IoWriteErrorLogEntry(ErrorLogEntry);
  457. }
  458. }
  459. SPX_MEM_COMPARES
  460. Spx_MemCompare(IN PHYSICAL_ADDRESS A, IN ULONG SpanOfA, IN PHYSICAL_ADDRESS B, IN ULONG SpanOfB)
  461. /*++
  462. Routine Description:
  463. Compare two phsical address.
  464. Arguments:
  465. A - One half of the comparison.
  466. SpanOfA - In units of bytes, the span of A.
  467. B - One half of the comparison.
  468. SpanOfB - In units of bytes, the span of B.
  469. Return Value:
  470. The result of the comparison.
  471. --*/
  472. {
  473. LARGE_INTEGER a;
  474. LARGE_INTEGER b;
  475. LARGE_INTEGER lower;
  476. ULONG lowerSpan;
  477. LARGE_INTEGER higher;
  478. PAGED_CODE(); // Macro in checked build to assert if pagable code is run at or above dispatch IRQL
  479. a = A;
  480. b = B;
  481. if(a.QuadPart == b.QuadPart)
  482. return AddressesAreEqual;
  483. if(a.QuadPart > b.QuadPart)
  484. {
  485. higher = a;
  486. lower = b;
  487. lowerSpan = SpanOfB;
  488. }
  489. else
  490. {
  491. higher = b;
  492. lower = a;
  493. lowerSpan = SpanOfA;
  494. }
  495. if((higher.QuadPart - lower.QuadPart) >= lowerSpan)
  496. return AddressesAreDisjoint;
  497. return AddressesOverlap;
  498. }
  499. NTSTATUS
  500. PLX_9050_CNTRL_REG_FIX(IN PCARD_DEVICE_EXTENSION pCard)
  501. {
  502. /********************************************************
  503. * Setting bit 17 in the CNTRL register of the PLX 9050 *
  504. * chip forces a retry on writes while a read is pending.*
  505. * This is to prevent the card locking up on Intel Xeon *
  506. * multiprocessor systems with the NX chipset. *
  507. ********************************************************/
  508. #define CNTRL_REG_OFFSET 0x14 // DWORD Offset (BYTE Offset 0x50)
  509. NTSTATUS status = STATUS_SUCCESS;
  510. PULONG pPCIConfigRegisters = NULL; // Pointer to PCI Config Registers.
  511. CHAR szErrorMsg[MAX_ERROR_LOG_INSERT]; // Limited to 51 characters + 1 null
  512. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Entering PLX_9050_CNTRL_REG_FIX for Card %d.\n",
  513. PRODUCT_NAME, pCard->CardNumber));
  514. pPCIConfigRegisters = MmMapIoSpace(pCard->PCIConfigRegisters, pCard->SpanOfPCIConfigRegisters, FALSE);
  515. if(pPCIConfigRegisters != NULL)
  516. {
  517. /* NOTE: If bit 7 of the PLX9050 config space physical address is set in either I/O Space or Memory...
  518. * ...then reads from the registers will only return 0. However, writes are OK. */
  519. if(pPCIConfigRegisters[CNTRL_REG_OFFSET] == 0) // If bit 7 is set Config Registers are zero (unreadable)
  520. {
  521. // We have to blindly write the value to the register.
  522. ((PUCHAR)pPCIConfigRegisters)[CNTRL_REG_OFFSET*4 + 2] |= 0x26; // Set bits 17 & 21 of PLX CNTRL register
  523. }
  524. else
  525. {
  526. ((PUCHAR)pPCIConfigRegisters)[CNTRL_REG_OFFSET*4 + 1] &= ~0x40; // Clear bit 14 of PLX CNTRL register
  527. ((PUCHAR)pPCIConfigRegisters)[CNTRL_REG_OFFSET*4 + 2] |= 0x26; // Set bits 17 & 21 of PLX CNTRL register
  528. }
  529. MmUnmapIoSpace(pPCIConfigRegisters, pCard->SpanOfPCIConfigRegisters);
  530. }
  531. else
  532. {
  533. SpxDbgMsg(SPX_TRACE_CALLS, ("%s: Insufficient resources available for Card %d.\n",
  534. PRODUCT_NAME, pCard->CardNumber));
  535. sprintf(szErrorMsg, "Card at %08X%08X: Insufficient resources.", pCard->PhysAddr.HighPart, pCard->PhysAddr.LowPart);
  536. Spx_LogMessage( STATUS_SEVERITY_ERROR,
  537. pCard->DriverObject, // Driver Object
  538. pCard->DeviceObject, // Device Object (Optional)
  539. PhysicalZero, // Physical Address 1
  540. PhysicalZero, // Physical Address 2
  541. 0, // SequenceNumber
  542. 0, // Major Function Code
  543. 0, // RetryCount
  544. FILE_ID | __LINE__, // UniqueErrorValue
  545. STATUS_SUCCESS, // FinalStatus
  546. szErrorMsg); // Error Message
  547. return STATUS_INSUFFICIENT_RESOURCES;
  548. }
  549. return status;
  550. }
  551. //
  552. // Definitely NON PAGABLE !!!
  553. //
  554. VOID
  555. SpxSetOrClearPnpPowerFlags(IN PCOMMON_OBJECT_DATA pDevExt, IN ULONG Value, IN BOOLEAN Set)
  556. {
  557. KIRQL oldIrql;
  558. KeAcquireSpinLock(&pDevExt->PnpPowerFlagsLock, &oldIrql);
  559. if(Set)
  560. pDevExt->PnpPowerFlags |= Value;
  561. else
  562. pDevExt->PnpPowerFlags &= ~Value;
  563. KeReleaseSpinLock(&pDevExt->PnpPowerFlagsLock, oldIrql);
  564. }
  565. // Definitely NON PAGABLE !!!
  566. //
  567. VOID
  568. SpxSetOrClearUnstallingFlag(IN PCOMMON_OBJECT_DATA pDevExt, IN BOOLEAN Set)
  569. {
  570. KIRQL oldIrql;
  571. KeAcquireSpinLock(&pDevExt->StalledIrpLock, &oldIrql);
  572. pDevExt->UnstallingFlag = Set;
  573. KeReleaseSpinLock(&pDevExt->StalledIrpLock, oldIrql);
  574. }
  575. // Definitely NON PAGABLE !!!
  576. //
  577. BOOLEAN
  578. SpxCheckPnpPowerFlags(IN PCOMMON_OBJECT_DATA pDevExt, IN ULONG ulSetFlags, IN ULONG ulClearedFlags, IN BOOLEAN bAll)
  579. {
  580. KIRQL oldIrql;
  581. BOOLEAN bRet = FALSE;
  582. KeAcquireSpinLock(&pDevExt->PnpPowerFlagsLock, &oldIrql);
  583. if(bAll)
  584. {
  585. // If all the requested SetFlags are set
  586. // and if all of the requested ClearedFlags are cleared then return true.
  587. if(((ulSetFlags & pDevExt->PnpPowerFlags) == ulSetFlags) && !(ulClearedFlags & pDevExt->PnpPowerFlags))
  588. bRet = TRUE;
  589. }
  590. else
  591. {
  592. // If any of the requested SetFlags are set
  593. // or if any of the requested ClearedFlags are cleared then return true.
  594. if((ulSetFlags & pDevExt->PnpPowerFlags) || (ulClearedFlags & ~pDevExt->PnpPowerFlags))
  595. bRet = TRUE;
  596. }
  597. KeReleaseSpinLock(&pDevExt->PnpPowerFlagsLock, oldIrql);
  598. return bRet;
  599. }
  600. PVOID
  601. SpxAllocateMem(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes)
  602. {
  603. PVOID pRet = NULL;
  604. pRet = ExAllocatePoolWithTag(PoolType, NumberOfBytes, MEMORY_TAG);
  605. if(pRet)
  606. RtlZeroMemory(pRet, NumberOfBytes); // Zero memory.
  607. return pRet;
  608. }
  609. PVOID
  610. SpxAllocateMemWithQuota(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes)
  611. {
  612. PVOID pRet = NULL;
  613. pRet = ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, MEMORY_TAG);
  614. if(pRet)
  615. RtlZeroMemory(pRet, NumberOfBytes); // Zero memory.
  616. return pRet;
  617. }
  618. #ifndef BUILD_SPXMINIPORT
  619. void
  620. SpxFreeMem(PVOID pMem)
  621. {
  622. ASSERT(pMem != NULL); // Assert if the pointer is NULL.
  623. ExFreePool(pMem);
  624. }
  625. #endif
  626. ///////////////////////////////////////////////////////////////////////////////////////////
  627. // Must be called just before an IoCompleteRequest if IrpCondition == IRP_SUBMITTED
  628. //
  629. ///////////////////////////////////////////////////////////////////////////////////////////
  630. VOID
  631. SpxIRPCounter(IN PPORT_DEVICE_EXTENSION pPort, IN PIRP pIrp, IN ULONG IrpCondition)
  632. {
  633. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  634. switch(pIrpStack->MajorFunction) // Don't filter Plug and Play IRPs
  635. {
  636. case IRP_MJ_FLUSH_BUFFERS:
  637. {
  638. switch(IrpCondition)
  639. {
  640. case IRP_SUBMITTED:
  641. pPort->PerfStats.FlushIrpsSubmitted++; // Increment counter for performance stats.
  642. break;
  643. case IRP_COMPLETED:
  644. {
  645. switch(pIrp->IoStatus.Status)
  646. {
  647. case STATUS_SUCCESS:
  648. pPort->PerfStats.FlushIrpsCompleted++; // Increment counter for performance stats.
  649. break;
  650. case STATUS_CANCELLED:
  651. pPort->PerfStats.FlushIrpsCancelled++; // Increment counter for performance stats.
  652. break;
  653. default:
  654. pPort->PerfStats.FlushIrpsCompleted++; // Increment counter for performance stats.
  655. break;
  656. }
  657. break;
  658. }
  659. case IRP_QUEUED:
  660. // InterlockedIncrement(&pPort->PerfStats.FlushIrpsQueued);
  661. pPort->PerfStats.FlushIrpsQueued++; // Increment counter for performance stats.
  662. break;
  663. case IRP_DEQUEUED:
  664. // InterlockedDecrement(&pPort->PerfStats.FlushIrpsQueued);
  665. if(pPort->PerfStats.FlushIrpsQueued)
  666. pPort->PerfStats.FlushIrpsQueued--; // Decrement counter for performance stats.
  667. break;
  668. default:
  669. break;
  670. }
  671. break;
  672. }
  673. case IRP_MJ_WRITE:
  674. {
  675. switch(IrpCondition)
  676. {
  677. case IRP_SUBMITTED:
  678. pPort->PerfStats.WriteIrpsSubmitted++; // Increment counter for performance stats.
  679. break;
  680. case IRP_COMPLETED:
  681. {
  682. switch(pIrp->IoStatus.Status)
  683. {
  684. case STATUS_SUCCESS:
  685. pPort->PerfStats.WriteIrpsCompleted++; // Increment counter for performance stats.
  686. break;
  687. case STATUS_CANCELLED:
  688. pPort->PerfStats.WriteIrpsCancelled++; // Increment counter for performance stats.
  689. break;
  690. case STATUS_TIMEOUT:
  691. pPort->PerfStats.WriteIrpsTimedOut++; // Increment counter for performance stats.
  692. break;
  693. default:
  694. pPort->PerfStats.WriteIrpsCompleted++; // Increment counter for performance stats.
  695. break;
  696. }
  697. break;
  698. }
  699. case IRP_QUEUED:
  700. // InterlockedIncrement(&pPort->PerfStats.WriteIrpsQueued);
  701. pPort->PerfStats.WriteIrpsQueued++; // Increment counter for performance stats.
  702. break;
  703. case IRP_DEQUEUED:
  704. // InterlockedDecrement(&pPort->PerfStats.WriteIrpsQueued);
  705. if(pPort->PerfStats.WriteIrpsQueued)
  706. pPort->PerfStats.WriteIrpsQueued--; // Decrement counter for performance stats.
  707. break;
  708. default:
  709. break;
  710. }
  711. break;
  712. }
  713. case IRP_MJ_READ:
  714. {
  715. switch(IrpCondition)
  716. {
  717. case IRP_SUBMITTED:
  718. pPort->PerfStats.ReadIrpsSubmitted++; // Increment counter for performance stats.
  719. break;
  720. case IRP_COMPLETED:
  721. {
  722. switch(pIrp->IoStatus.Status)
  723. {
  724. case STATUS_SUCCESS:
  725. pPort->PerfStats.ReadIrpsCompleted++; // Increment counter for performance stats.
  726. break;
  727. case STATUS_CANCELLED:
  728. pPort->PerfStats.ReadIrpsCancelled++; // Increment counter for performance stats.
  729. break;
  730. case STATUS_TIMEOUT:
  731. pPort->PerfStats.ReadIrpsTimedOut++; // Increment counter for performance stats.
  732. break;
  733. default:
  734. pPort->PerfStats.ReadIrpsCompleted++; // Increment counter for performance stats.
  735. break;
  736. }
  737. break;
  738. }
  739. case IRP_QUEUED:
  740. // InterlockedIncrement(&pPort->PerfStats.ReadIrpsQueued);
  741. pPort->PerfStats.ReadIrpsQueued++; // Increment counter for performance stats.
  742. break;
  743. case IRP_DEQUEUED:
  744. // InterlockedDecrement(&pPort->PerfStats.ReadIrpsQueued);
  745. if(pPort->PerfStats.ReadIrpsQueued)
  746. pPort->PerfStats.ReadIrpsQueued--; // Decrement counter for performance stats.
  747. break;
  748. default:
  749. break;
  750. }
  751. break;
  752. }
  753. case IRP_MJ_DEVICE_CONTROL:
  754. {
  755. switch(IrpCondition)
  756. {
  757. case IRP_SUBMITTED:
  758. pPort->PerfStats.IoctlIrpsSubmitted++; // Increment counter for performance stats.
  759. break;
  760. case IRP_COMPLETED:
  761. {
  762. switch(pIrp->IoStatus.Status)
  763. {
  764. case STATUS_SUCCESS:
  765. pPort->PerfStats.IoctlIrpsCompleted++; // Increment counter for performance stats.
  766. break;
  767. case STATUS_CANCELLED:
  768. pPort->PerfStats.IoctlIrpsCancelled++; // Increment counter for performance stats.
  769. break;
  770. default:
  771. pPort->PerfStats.IoctlIrpsCompleted++; // Increment counter for performance stats.
  772. break;
  773. }
  774. break;
  775. }
  776. default:
  777. break;
  778. }
  779. break;
  780. }
  781. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  782. {
  783. switch(IrpCondition)
  784. {
  785. case IRP_SUBMITTED:
  786. pPort->PerfStats.InternalIoctlIrpsSubmitted++; // Increment counter for performance stats.
  787. break;
  788. case IRP_COMPLETED:
  789. {
  790. switch(pIrp->IoStatus.Status)
  791. {
  792. case STATUS_SUCCESS:
  793. pPort->PerfStats.InternalIoctlIrpsCompleted++; // Increment counter for performance stats.
  794. break;
  795. case STATUS_CANCELLED:
  796. pPort->PerfStats.InternalIoctlIrpsCancelled++; // Increment counter for performance stats.
  797. break;
  798. default:
  799. pPort->PerfStats.InternalIoctlIrpsCompleted++; // Increment counter for performance stats.
  800. break;
  801. }
  802. break;
  803. }
  804. default:
  805. break;
  806. }
  807. break;
  808. }
  809. case IRP_MJ_CREATE:
  810. {
  811. switch(IrpCondition)
  812. {
  813. case IRP_SUBMITTED:
  814. pPort->PerfStats.CreateIrpsSubmitted++; // Increment counter for performance stats.
  815. break;
  816. case IRP_COMPLETED:
  817. {
  818. switch(pIrp->IoStatus.Status)
  819. {
  820. case STATUS_SUCCESS:
  821. pPort->PerfStats.CreateIrpsCompleted++; // Increment counter for performance stats.
  822. break;
  823. case STATUS_CANCELLED:
  824. pPort->PerfStats.CreateIrpsCancelled++; // Increment counter for performance stats.
  825. break;
  826. default:
  827. pPort->PerfStats.CreateIrpsCompleted++; // Increment counter for performance stats.
  828. break;
  829. }
  830. break;
  831. }
  832. default:
  833. break;
  834. }
  835. break;
  836. }
  837. case IRP_MJ_CLOSE:
  838. {
  839. switch(IrpCondition)
  840. {
  841. case IRP_SUBMITTED:
  842. pPort->PerfStats.CloseIrpsSubmitted++; // Increment counter for performance stats.
  843. break;
  844. case IRP_COMPLETED:
  845. {
  846. switch(pIrp->IoStatus.Status)
  847. {
  848. case STATUS_SUCCESS:
  849. pPort->PerfStats.CloseIrpsCompleted++; // Increment counter for performance stats.
  850. break;
  851. case STATUS_CANCELLED:
  852. pPort->PerfStats.CloseIrpsCancelled++; // Increment counter for performance stats.
  853. break;
  854. default:
  855. pPort->PerfStats.CloseIrpsCompleted++; // Increment counter for performance stats.
  856. break;
  857. }
  858. break;
  859. }
  860. default:
  861. break;
  862. }
  863. break;
  864. }
  865. case IRP_MJ_CLEANUP:
  866. {
  867. switch(IrpCondition)
  868. {
  869. case IRP_SUBMITTED:
  870. pPort->PerfStats.CleanUpIrpsSubmitted++; // Increment counter for performance stats.
  871. break;
  872. case IRP_COMPLETED:
  873. {
  874. switch(pIrp->IoStatus.Status)
  875. {
  876. case STATUS_SUCCESS:
  877. pPort->PerfStats.CleanUpIrpsCompleted++; // Increment counter for performance stats.
  878. break;
  879. case STATUS_CANCELLED:
  880. pPort->PerfStats.CleanUpIrpsCancelled++; // Increment counter for performance stats.
  881. break;
  882. default:
  883. pPort->PerfStats.CleanUpIrpsCompleted++; // Increment counter for performance stats.
  884. break;
  885. }
  886. break;
  887. }
  888. default:
  889. break;
  890. }
  891. break;
  892. }
  893. case IRP_MJ_QUERY_INFORMATION:
  894. case IRP_MJ_SET_INFORMATION:
  895. {
  896. switch(IrpCondition)
  897. {
  898. case IRP_SUBMITTED:
  899. pPort->PerfStats.InfoIrpsSubmitted++; // Increment counter for performance stats.
  900. break;
  901. case IRP_COMPLETED:
  902. {
  903. switch(pIrp->IoStatus.Status)
  904. {
  905. case STATUS_SUCCESS:
  906. pPort->PerfStats.InfoIrpsCompleted++; // Increment counter for performance stats.
  907. break;
  908. case STATUS_CANCELLED:
  909. pPort->PerfStats.InfoIrpsCancelled++; // Increment counter for performance stats.
  910. break;
  911. default:
  912. pPort->PerfStats.InfoIrpsCompleted++; // Increment counter for performance stats.
  913. break;
  914. }
  915. break;
  916. }
  917. default:
  918. break;
  919. }
  920. break;
  921. }
  922. default:
  923. break;
  924. }
  925. }
  926. ////////////////////////////////////////////////////////////////////////////////
  927. // Prototype: BOOLEAN SpxClearAllPortStats(IN PPORT_DEVICE_EXTENSION pPort)
  928. //
  929. // Routine Description:
  930. // In sync with the interrpt service routine (which sets the perf stats)
  931. // clear the perf stats.
  932. //
  933. // Arguments:
  934. // pPort - Pointer to a the Port Device Extension.
  935. //
  936. ////////////////////////////////////////////////////////////////////////////////
  937. BOOLEAN SpxClearAllPortStats(IN PPORT_DEVICE_EXTENSION pPort)
  938. {
  939. RtlZeroMemory(&pPort->PerfStats, sizeof(PORT_PERFORMANCE_STATS));
  940. return FALSE;
  941. }