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.

423 lines
9.9 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. This module contains utility functions for the pcmcia driver
  7. Authors:
  8. Bob Rinne (BobRi) 3-Aug-1994
  9. Jeff McLeman 12-Apr-1994
  10. Ravisankar Pudipeddi (ravisp) 1-Nov-96
  11. Neil Sandlin (neilsa) June 1 1999
  12. Environment:
  13. Kernel mode
  14. Revision History :
  15. 6-Apr-95
  16. Modified for databook support - John Keys Databook
  17. 1-Nov-96
  18. Total overhaul to make this a bus enumerator - Ravisankar Pudipeddi (ravisp)
  19. 30-Mar-99
  20. Turn this module into really just utility routines
  21. --*/
  22. #include "pch.h"
  23. #pragma alloc_text(PAGE, PcmciaReportControllerError)
  24. //
  25. // Internal References
  26. //
  27. NTSTATUS
  28. PcmciaAdapterIoCompletion(
  29. IN PDEVICE_OBJECT DeviceObject,
  30. IN PIRP Irp,
  31. IN PKEVENT pdoIoCompletedEvent
  32. );
  33. //
  34. //
  35. //
  36. NTSTATUS
  37. PcmciaIoCallDriverSynchronous(
  38. PDEVICE_OBJECT deviceObject,
  39. PIRP Irp
  40. )
  41. /*++
  42. Routine Description
  43. Arguments
  44. Return Value
  45. --*/
  46. {
  47. NTSTATUS status;
  48. KEVENT event;
  49. KeInitializeEvent(&event, NotificationEvent, FALSE);
  50. IoCopyCurrentIrpStackLocationToNext(Irp);
  51. IoSetCompletionRoutine(
  52. Irp,
  53. PcmciaAdapterIoCompletion,
  54. &event,
  55. TRUE,
  56. TRUE,
  57. TRUE
  58. );
  59. status = IoCallDriver(deviceObject, Irp);
  60. if (status == STATUS_PENDING) {
  61. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  62. status = Irp->IoStatus.Status;
  63. }
  64. return status;
  65. }
  66. NTSTATUS
  67. PcmciaAdapterIoCompletion(
  68. IN PDEVICE_OBJECT DeviceObject,
  69. IN PIRP Irp,
  70. IN PKEVENT pdoIoCompletedEvent
  71. )
  72. /*++
  73. Routine Description:
  74. Generic completion routine used by the driver
  75. Arguments:
  76. DeviceObject
  77. Irp
  78. pdoIoCompletedEvent - this event will be signalled before return of this routine
  79. Return value:
  80. Status
  81. --*/
  82. {
  83. KeSetEvent(pdoIoCompletedEvent, IO_NO_INCREMENT, FALSE);
  84. return STATUS_MORE_PROCESSING_REQUIRED;
  85. }
  86. VOID
  87. PcmciaWait(
  88. IN ULONG MicroSeconds
  89. )
  90. /*++
  91. Routine Description
  92. Waits for the specified interval before returning,
  93. by yielding execution.
  94. Arguments
  95. MicroSeconds - Amount of time to delay in microseconds
  96. Return Value
  97. None. Must succeed.
  98. --*/
  99. {
  100. LARGE_INTEGER dueTime;
  101. NTSTATUS status;
  102. if ((KeGetCurrentIrql() < DISPATCH_LEVEL) && (MicroSeconds > 50)) {
  103. //
  104. // Convert delay to 100-nanosecond intervals
  105. //
  106. dueTime.QuadPart = -((LONG) MicroSeconds*10);
  107. //
  108. // We wait for an event that'll never be set.
  109. //
  110. status = KeWaitForSingleObject(&PcmciaDelayTimerEvent,
  111. Executive,
  112. KernelMode,
  113. FALSE,
  114. &dueTime);
  115. ASSERT(status == STATUS_TIMEOUT);
  116. } else {
  117. KeStallExecutionProcessor(MicroSeconds);
  118. }
  119. }
  120. ULONG
  121. PcmciaCountOnes(
  122. IN ULONG Data
  123. )
  124. /*++
  125. Routine Description:
  126. Counts the number of 1's in the binary representation of the supplied argument
  127. Arguments:
  128. Data - supplied argument for which 1's need to be counted
  129. Return value:
  130. Number of 1's in binary rep. of Data
  131. --*/
  132. {
  133. ULONG count=0;
  134. while (Data) {
  135. Data &= (Data-1);
  136. count++;
  137. }
  138. return count;
  139. }
  140. VOID
  141. PcmciaLogError(
  142. IN PFDO_EXTENSION DeviceExtension,
  143. IN ULONG ErrorCode,
  144. IN ULONG UniqueId,
  145. IN ULONG Argument
  146. )
  147. /*++
  148. Routine Description:
  149. This function logs an error.
  150. Arguments:
  151. DeviceExtension - Supplies a pointer to the port device extension.
  152. ErrorCode - Supplies the error code for this error.
  153. UniqueId - Supplies the UniqueId for this error.
  154. Return Value:
  155. None.
  156. --*/
  157. {
  158. PIO_ERROR_LOG_PACKET packet;
  159. packet = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(DeviceExtension->DeviceObject,
  160. sizeof(IO_ERROR_LOG_PACKET) + sizeof(ULONG));
  161. if (packet) {
  162. packet->ErrorCode = ErrorCode;
  163. packet->SequenceNumber = DeviceExtension->SequenceNumber++;
  164. packet->MajorFunctionCode = 0;
  165. packet->RetryCount = (UCHAR) 0;
  166. packet->UniqueErrorValue = UniqueId;
  167. packet->FinalStatus = STATUS_SUCCESS;
  168. packet->DumpDataSize = sizeof(ULONG);
  169. packet->DumpData[0] = Argument;
  170. IoWriteErrorLogEntry(packet);
  171. }
  172. }
  173. VOID
  174. PcmciaLogErrorWithStrings(
  175. IN PFDO_EXTENSION DeviceExtension,
  176. IN ULONG ErrorCode,
  177. IN ULONG UniqueId,
  178. IN PUNICODE_STRING String1,
  179. IN PUNICODE_STRING String2
  180. )
  181. /*++
  182. Routine Description
  183. This function logs an error and includes the strings provided.
  184. Arguments:
  185. DeviceExtension - Supplies a pointer to the port device extension.
  186. ErrorCode - Supplies the error code for this error.
  187. UniqueId - Supplies the UniqueId for this error.
  188. String1 - The first string to be inserted.
  189. String2 - The second string to be inserted.
  190. Return Value:
  191. None.
  192. --*/
  193. {
  194. ULONG length;
  195. PCHAR dumpData;
  196. PIO_ERROR_LOG_PACKET packet;
  197. length = String1->Length + sizeof(IO_ERROR_LOG_PACKET) + 4;
  198. if (String2) {
  199. length += String2->Length;
  200. }
  201. if (length > ERROR_LOG_MAXIMUM_SIZE) {
  202. //
  203. // Don't have code to truncate strings so don't log this.
  204. //
  205. return;
  206. }
  207. packet = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(DeviceExtension->DeviceObject,
  208. (UCHAR) length);
  209. if (packet) {
  210. packet->ErrorCode = ErrorCode;
  211. packet->SequenceNumber = DeviceExtension->SequenceNumber++;
  212. packet->MajorFunctionCode = 0;
  213. packet->RetryCount = (UCHAR) 0;
  214. packet->UniqueErrorValue = UniqueId;
  215. packet->FinalStatus = STATUS_SUCCESS;
  216. packet->NumberOfStrings = 1;
  217. packet->StringOffset = (USHORT) ((PUCHAR)&packet->DumpData[0] - (PUCHAR)packet);
  218. packet->DumpDataSize = (USHORT) (length - sizeof(IO_ERROR_LOG_PACKET));
  219. packet->DumpDataSize /= sizeof(ULONG);
  220. dumpData = (PUCHAR) &packet->DumpData[0];
  221. RtlCopyMemory(dumpData, String1->Buffer, String1->Length);
  222. dumpData += String1->Length;
  223. if (String2) {
  224. *dumpData++ = '\\';
  225. *dumpData++ = '\0';
  226. RtlCopyMemory(dumpData, String2->Buffer, String2->Length);
  227. dumpData += String2->Length;
  228. }
  229. *dumpData++ = '\0';
  230. *dumpData++ = '\0';
  231. IoWriteErrorLogEntry(packet);
  232. }
  233. return;
  234. }
  235. BOOLEAN
  236. PcmciaReportControllerError(
  237. IN PFDO_EXTENSION FdoExtension,
  238. NTSTATUS ErrorCode
  239. )
  240. /*++
  241. Routine Description
  242. Causes a pop-up dialog to appear indicating an error that
  243. we should tell the user about. The device description of the
  244. controller is also included in the text of the pop-up.
  245. Arguments
  246. FdoExtension - Pointer to device extension for pcmcia controller
  247. ErrorCode - the ntstatus code for the error
  248. Return Value
  249. TRUE - If a an error was queued
  250. FALSE - If it failed for some reason
  251. --*/
  252. {
  253. UNICODE_STRING unicodeString;
  254. PWSTR deviceDesc = NULL;
  255. NTSTATUS status;
  256. ULONG length = 0;
  257. BOOLEAN retVal;
  258. PAGED_CODE();
  259. //
  260. // Obtain the device description for the PCMCIA controller
  261. // that is used in the error pop-up. If one cannot be obtained,
  262. // still pop-up the error dialog, indicating the controller as unknown
  263. //
  264. // First, find out the length of the buffer required to obtain
  265. // device description for this pcmcia controller
  266. //
  267. status = IoGetDeviceProperty(FdoExtension->Pdo,
  268. DevicePropertyDeviceDescription,
  269. 0,
  270. NULL,
  271. &length
  272. );
  273. ASSERT(!NT_SUCCESS(status));
  274. if (status == STATUS_BUFFER_TOO_SMALL) {
  275. deviceDesc = ExAllocatePool(PagedPool, length);
  276. if (deviceDesc != NULL) {
  277. status = IoGetDeviceProperty(FdoExtension->Pdo,
  278. DevicePropertyDeviceDescription,
  279. length,
  280. deviceDesc,
  281. &length);
  282. if (!NT_SUCCESS(status)) {
  283. ExFreePool(deviceDesc);
  284. }
  285. } else {
  286. status = STATUS_INSUFFICIENT_RESOURCES;
  287. }
  288. }
  289. if (!NT_SUCCESS(status)) {
  290. deviceDesc = L"[unknown]";
  291. }
  292. RtlInitUnicodeString(&unicodeString, deviceDesc);
  293. retVal = IoRaiseInformationalHardError(
  294. ErrorCode,
  295. &unicodeString,
  296. NULL);
  297. //
  298. // Note: successful status here indicates success of
  299. // IoGetDeviceProperty above. This would mean we still have an
  300. // allocated buffer.
  301. //
  302. if (NT_SUCCESS(status)) {
  303. ExFreePool(deviceDesc);
  304. }
  305. return retVal;
  306. }