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.

666 lines
16 KiB

  1. /*++
  2. Module Name:
  3. Mxenum.C
  4. Abstract:
  5. This module contains contains the entry points
  6. for a serial port bus enumerator PNP / WDM driver.
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include <ntddk.h>
  13. #include <devioctl.h>
  14. #include <initguid.h>
  15. #include <wdmguid.h>
  16. #include <ntddser.h>
  17. #include "mxenum.h"
  18. static const PHYSICAL_ADDRESS SerialPhysicalZero = {0};
  19. PWSTR BoardDesc[5]={
  20. L"C218Turbo",
  21. L"C218Turbo/PCI",
  22. L"C320Turbo",
  23. L"C320Turbo/PCI",
  24. L"CP-204J"
  25. };
  26. PWSTR DownloadErrMsg[7]={
  27. L"Fimware file not found or bad",
  28. L"Board not found",
  29. L"CPU module not found",
  30. L"Download fail",
  31. L"Download fail",
  32. L"CPU module download fail",
  33. L"UART module fail"
  34. };
  35. ULONG NumBoardInstalled;
  36. //
  37. // Declare some entry functions as pageable, and make DriverEntry
  38. // discardable
  39. //
  40. NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING);
  41. #ifdef ALLOC_PRAGMA
  42. #pragma alloc_text(INIT, DriverEntry)
  43. #pragma alloc_text(PAGE, MxenumDriverUnload)
  44. #pragma alloc_text(PAGE,MxenumLogError)
  45. #endif
  46. NTSTATUS
  47. DriverEntry (
  48. IN PDRIVER_OBJECT DriverObject,
  49. IN PUNICODE_STRING UniRegistryPath
  50. )
  51. /*++
  52. Routine Description:
  53. Initialize the entry points of the driver.
  54. --*/
  55. {
  56. ULONG i;
  57. #if !DBG
  58. UNREFERENCED_PARAMETER (UniRegistryPath);
  59. #endif
  60. MxenumKdPrint (MXENUM_DBG_TRACE,("Driver Entry\n"));
  61. MxenumKdPrint (MXENUM_DBG_TRACE, ("RegPath: %ws\n", UniRegistryPath->Buffer));
  62. //
  63. // Set ever slot to initially pass the request through to the lower
  64. // device object
  65. //
  66. for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
  67. DriverObject->MajorFunction[i] = MxenumDispatchPassThrough;
  68. }
  69. DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL]
  70. = MxenumInternIoCtl;
  71. DriverObject->MajorFunction [IRP_MJ_PNP] = MxenumPnPDispatch;
  72. DriverObject->MajorFunction [IRP_MJ_POWER] = MxenumPowerDispatch;
  73. DriverObject->DriverUnload = MxenumDriverUnload;
  74. DriverObject->DriverExtension->AddDevice = MxenumAddDevice;
  75. NumBoardInstalled = 0;
  76. return STATUS_SUCCESS;
  77. }
  78. NTSTATUS
  79. MxenumSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
  80. IN PKEVENT SerenumSyncEvent)
  81. {
  82. UNREFERENCED_PARAMETER(DeviceObject);
  83. UNREFERENCED_PARAMETER(Irp);
  84. KeSetEvent(SerenumSyncEvent, IO_NO_INCREMENT, FALSE);
  85. return STATUS_MORE_PROCESSING_REQUIRED;
  86. }
  87. NTSTATUS
  88. MxenumInternIoCtl (
  89. PDEVICE_OBJECT DeviceObject,
  90. IN PIRP Irp
  91. )
  92. /*++
  93. Routine Description:
  94. --*/
  95. {
  96. PIO_STACK_LOCATION pIrpStack;
  97. NTSTATUS status;
  98. PCOMMON_DEVICE_DATA commonData;
  99. PPDO_DEVICE_DATA pdoData;
  100. PFDO_DEVICE_DATA fdoData;
  101. // PAGED_CODE();
  102. status = STATUS_SUCCESS;
  103. pIrpStack = IoGetCurrentIrpStackLocation (Irp);
  104. // ASSERT (IRP_MJ_INTERNAL_DEVICE_CONTROL == pIrpStack->MajorFunction);
  105. commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
  106. pdoData = (PPDO_DEVICE_DATA) DeviceObject->DeviceExtension;
  107. //
  108. // We only take Internal Device Control requests for the PDO.
  109. // That is the objects on the bus (representing the serial ports)
  110. if (commonData->IsFDO) {
  111. status = STATUS_ACCESS_DENIED;
  112. } else if (pdoData->Removed) {
  113. //
  114. // This bus has received the PlugPlay remove IRP. It will no longer
  115. // respond to external requests.
  116. //
  117. status = STATUS_DELETE_PENDING;
  118. } else {
  119. switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
  120. case IOCTL_MOXA_INTERNAL_BASIC_SETTINGS :
  121. {
  122. PDEVICE_SETTINGS pSettings;
  123. long len;
  124. MxenumKdPrint(MXENUM_DBG_TRACE, ("Get Settings\n"));
  125. //
  126. // Check the buffer size
  127. //
  128. if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  129. sizeof(DEVICE_SETTINGS)) {
  130. MxenumKdPrint(MXENUM_DBG_TRACE, ("Output buffer too small\n"));
  131. status = STATUS_BUFFER_TOO_SMALL;
  132. break;
  133. }
  134. Irp->IoStatus.Information = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  135. pSettings = (PDEVICE_SETTINGS)Irp->AssociatedIrp.SystemBuffer;
  136. fdoData = (PFDO_DEVICE_DATA)(pdoData->ParentFdo->DeviceExtension);
  137. pSettings->BoardIndex = fdoData->BoardIndex;
  138. pSettings->PortIndex = pdoData->PortIndex;
  139. pSettings->BoardType = fdoData->BoardType;
  140. pSettings->NumPorts = fdoData->NumPorts;
  141. pSettings->InterfaceType = fdoData->InterfaceType;
  142. pSettings->BusNumber = fdoData->BusNumber;
  143. RtlCopyMemory(&pSettings->OriginalAckPort,&fdoData->OriginalAckPort,sizeof(PHYSICAL_ADDRESS));
  144. RtlCopyMemory(&pSettings->OriginalBaseAddress,&fdoData->OriginalBaseAddress,sizeof(PHYSICAL_ADDRESS));
  145. pSettings->BaseAddress = fdoData->BaseAddress;
  146. pSettings->AckPort = fdoData->AckPort;
  147. pSettings->Interrupt.Level = fdoData->Interrupt.Level;
  148. pSettings->Interrupt.Vector = fdoData->Interrupt.Vector;
  149. pSettings->Interrupt.Affinity = fdoData->Interrupt.Affinity;
  150. status = STATUS_SUCCESS;
  151. MxenumKdPrint(MXENUM_DBG_TRACE, ("OK\n"));
  152. break;
  153. }
  154. case IOCTL_MOXA_INTERNAL_BOARD_READY :
  155. {
  156. MxenumKdPrint(MXENUM_DBG_TRACE, ("Get board ready\n"));
  157. //
  158. // Check the buffer size
  159. //
  160. if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength <
  161. sizeof(ULONG)) {
  162. MxenumKdPrint(MXENUM_DBG_TRACE, ("Output buffer too small\n"));
  163. status = STATUS_BUFFER_TOO_SMALL;
  164. break;
  165. }
  166. Irp->IoStatus.Information = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  167. fdoData = (PFDO_DEVICE_DATA)(pdoData->ParentFdo->DeviceExtension);
  168. if (fdoData->Started == TRUE) {
  169. *(PULONG)Irp->AssociatedIrp.SystemBuffer = 1;
  170. MxenumKdPrint(MXENUM_DBG_TRACE, ("This board is ready\n"));
  171. }
  172. else {
  173. *(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
  174. MxenumKdPrint(MXENUM_DBG_TRACE, ("This board is not ready\n"));
  175. }
  176. break;
  177. }
  178. default:
  179. status = STATUS_INVALID_PARAMETER;
  180. }
  181. }
  182. Irp->IoStatus.Status = status;
  183. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  184. return status;
  185. }
  186. VOID
  187. MxenumDriverUnload (
  188. IN PDRIVER_OBJECT Driver
  189. )
  190. /*++
  191. Routine Description:
  192. Clean up everything we did in driver entry.
  193. --*/
  194. {
  195. UNREFERENCED_PARAMETER (Driver);
  196. PAGED_CODE();
  197. MxenumKdPrint(MXENUM_DBG_TRACE, ("Driver unload\n"));
  198. //
  199. // All the device objects should be gone.
  200. //
  201. // ASSERT (NULL == Driver->DeviceObject);
  202. //
  203. // Here we free any resources allocated in DriverEntry
  204. //
  205. return;
  206. }
  207. NTSTATUS
  208. MxenumIncIoCount (
  209. PFDO_DEVICE_DATA Data
  210. )
  211. {
  212. InterlockedIncrement (&Data->OutstandingIO);
  213. if (Data->Removed) {
  214. if (0 == InterlockedDecrement (&Data->OutstandingIO)) {
  215. KeSetEvent (&Data->RemoveEvent, 0, FALSE);
  216. }
  217. return STATUS_DELETE_PENDING;
  218. }
  219. return STATUS_SUCCESS;
  220. }
  221. VOID
  222. MxenumDecIoCount (
  223. PFDO_DEVICE_DATA Data
  224. )
  225. {
  226. if (0 == InterlockedDecrement (&Data->OutstandingIO)) {
  227. KeSetEvent (&Data->RemoveEvent, 0, FALSE);
  228. }
  229. }
  230. NTSTATUS
  231. MxenumDispatchPassThrough(
  232. IN PDEVICE_OBJECT DeviceObject,
  233. IN PIRP Irp
  234. )
  235. /*++
  236. Routine Description:
  237. Passes a request on to the lower driver.
  238. --*/
  239. {
  240. PIO_STACK_LOCATION IrpStack =
  241. IoGetCurrentIrpStackLocation( Irp );
  242. #if 0
  243. MxenumKdPrint(MXENUM_DBG_TRACE,
  244. ("[MxenumDispatchPassThrough] "
  245. "IRP: %8x; "
  246. "MajorFunction: %d\n",
  247. Irp,
  248. IrpStack->MajorFunction ));
  249. #endif
  250. //
  251. // Pass the IRP to the target
  252. //
  253. IoSkipCurrentIrpStackLocation (Irp);
  254. // BUGBUG: VERIFY THIS FUNCTIONS CORRECTLY!!!
  255. if (((PPDO_DEVICE_DATA) DeviceObject->DeviceExtension)->IsFDO) {
  256. return IoCallDriver(
  257. ((PFDO_DEVICE_DATA) DeviceObject->DeviceExtension)->TopOfStack,
  258. Irp );
  259. } else {
  260. return IoCallDriver(
  261. ((PFDO_DEVICE_DATA) ((PPDO_DEVICE_DATA) DeviceObject->
  262. DeviceExtension)->ParentFdo->DeviceExtension)->TopOfStack,
  263. Irp );
  264. }
  265. }
  266. MXENUM_MEM_COMPARES
  267. MxenumMemCompare(
  268. IN PHYSICAL_ADDRESS A,
  269. IN ULONG SpanOfA,
  270. IN PHYSICAL_ADDRESS B,
  271. IN ULONG SpanOfB
  272. )
  273. /*++
  274. Routine Description:
  275. Compare two phsical address.
  276. Arguments:
  277. A - One half of the comparison.
  278. SpanOfA - In units of bytes, the span of A.
  279. B - One half of the comparison.
  280. SpanOfB - In units of bytes, the span of B.
  281. Return Value:
  282. The result of the comparison.
  283. --*/
  284. {
  285. LARGE_INTEGER a;
  286. LARGE_INTEGER b;
  287. LARGE_INTEGER lower;
  288. ULONG lowerSpan;
  289. LARGE_INTEGER higher;
  290. a = A;
  291. b = B;
  292. if (a.QuadPart == b.QuadPart) {
  293. return AddressesAreEqual;
  294. }
  295. if (a.QuadPart > b.QuadPart) {
  296. higher = a;
  297. lower = b;
  298. lowerSpan = SpanOfB;
  299. } else {
  300. higher = b;
  301. lower = a;
  302. lowerSpan = SpanOfA;
  303. }
  304. if ((higher.QuadPart - lower.QuadPart) >= lowerSpan) {
  305. return AddressesAreDisjoint;
  306. }
  307. return AddressesOverlap;
  308. }
  309. VOID
  310. MxenumLogError(
  311. IN PDRIVER_OBJECT DriverObject,
  312. IN PDEVICE_OBJECT DeviceObject OPTIONAL,
  313. IN PHYSICAL_ADDRESS P1,
  314. IN PHYSICAL_ADDRESS P2,
  315. IN ULONG SequenceNumber,
  316. IN UCHAR MajorFunctionCode,
  317. IN UCHAR RetryCount,
  318. IN ULONG UniqueErrorValue,
  319. IN NTSTATUS FinalStatus,
  320. IN NTSTATUS SpecificIOStatus,
  321. IN ULONG LengthOfInsert1,
  322. IN PWCHAR Insert1,
  323. IN ULONG LengthOfInsert2,
  324. IN PWCHAR Insert2
  325. )
  326. /*++
  327. Routine Description:
  328. This routine allocates an error log entry, copies the supplied data
  329. to it, and requests that it be written to the error log file.
  330. Arguments:
  331. DriverObject - A pointer to the driver object for the device.
  332. DeviceObject - A pointer to the device object associated with the
  333. device that had the error, early in initialization, one may not
  334. yet exist.
  335. P1,P2 - If phyical addresses for the controller ports involved
  336. with the error are available, put them through as dump data.
  337. SequenceNumber - A ulong value that is unique to an IRP over the
  338. life of the irp in this driver - 0 generally means an error not
  339. associated with an irp.
  340. MajorFunctionCode - If there is an error associated with the irp,
  341. this is the major function code of that irp.
  342. RetryCount - The number of times a particular operation has been
  343. retried.
  344. UniqueErrorValue - A unique long word that identifies the particular
  345. call to this function.
  346. FinalStatus - The final status given to the irp that was associated
  347. with this error. If this log entry is being made during one of
  348. the retries this value will be STATUS_SUCCESS.
  349. SpecificIOStatus - The IO status for a particular error.
  350. LengthOfInsert1 - The length in bytes (including the terminating NULL)
  351. of the first insertion string.
  352. Insert1 - The first insertion string.
  353. LengthOfInsert2 - The length in bytes (including the terminating NULL)
  354. of the second insertion string. NOTE, there must
  355. be a first insertion string for their to be
  356. a second insertion string.
  357. Insert2 - The second insertion string.
  358. Return Value:
  359. None.
  360. --*/
  361. {
  362. PIO_ERROR_LOG_PACKET errorLogEntry;
  363. PVOID objectToUse;
  364. SHORT dumpToAllocate = 0;
  365. PUCHAR ptrToFirstInsert;
  366. PUCHAR ptrToSecondInsert;
  367. if (ARGUMENT_PRESENT(DeviceObject)) {
  368. objectToUse = DeviceObject;
  369. } else {
  370. objectToUse = DriverObject;
  371. }
  372. if (MxenumMemCompare(
  373. P1,
  374. (ULONG)1,
  375. SerialPhysicalZero,
  376. (ULONG)1
  377. ) != AddressesAreEqual) {
  378. dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS);
  379. }
  380. if (MxenumMemCompare(
  381. P2,
  382. (ULONG)1,
  383. SerialPhysicalZero,
  384. (ULONG)1
  385. ) != AddressesAreEqual) {
  386. dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS);
  387. }
  388. errorLogEntry = IoAllocateErrorLogEntry(
  389. objectToUse,
  390. (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
  391. dumpToAllocate + LengthOfInsert1 +
  392. LengthOfInsert2)
  393. );
  394. if ( errorLogEntry != NULL ) {
  395. RtlZeroMemory(
  396. (PUCHAR)errorLogEntry,
  397. (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
  398. dumpToAllocate + LengthOfInsert1 +
  399. LengthOfInsert2)
  400. );
  401. errorLogEntry->ErrorCode = SpecificIOStatus;
  402. errorLogEntry->SequenceNumber = SequenceNumber;
  403. errorLogEntry->MajorFunctionCode = MajorFunctionCode;
  404. errorLogEntry->RetryCount = RetryCount;
  405. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  406. errorLogEntry->FinalStatus = FinalStatus;
  407. errorLogEntry->DumpDataSize = dumpToAllocate;
  408. if (dumpToAllocate) {
  409. RtlCopyMemory(
  410. &errorLogEntry->DumpData[0],
  411. &P1,
  412. sizeof(PHYSICAL_ADDRESS)
  413. );
  414. if (dumpToAllocate > sizeof(PHYSICAL_ADDRESS)) {
  415. RtlCopyMemory(
  416. ((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS),
  417. &P2,
  418. sizeof(PHYSICAL_ADDRESS)
  419. );
  420. ptrToFirstInsert =
  421. ((PUCHAR)&errorLogEntry->DumpData[0])+(2*sizeof(PHYSICAL_ADDRESS));
  422. } else {
  423. ptrToFirstInsert =
  424. ((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS);
  425. }
  426. } else {
  427. ptrToFirstInsert = (PUCHAR)&errorLogEntry->DumpData[0];
  428. }
  429. ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1;
  430. if (LengthOfInsert1) {
  431. errorLogEntry->NumberOfStrings = 1;
  432. errorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert -
  433. (PUCHAR)errorLogEntry);
  434. RtlCopyMemory(
  435. ptrToFirstInsert,
  436. Insert1,
  437. LengthOfInsert1
  438. );
  439. if (LengthOfInsert2) {
  440. errorLogEntry->NumberOfStrings = 2;
  441. RtlCopyMemory(
  442. ptrToSecondInsert,
  443. Insert2,
  444. LengthOfInsert2
  445. );
  446. }
  447. }
  448. IoWriteErrorLogEntry(errorLogEntry);
  449. }
  450. }
  451. VOID
  452. MxenumHexToString(PWSTR buffer, int port)
  453. {
  454. unsigned short io;
  455. buffer[0] = '0';
  456. buffer[1] = 'x';
  457. io = (USHORT)port;
  458. io >>= 12;
  459. io &= 0x000F;
  460. buffer[2] = (WCHAR)('0' + io);
  461. if ( io >= 0x000A )
  462. buffer[2] += (WCHAR)('A' - '9' - 1);
  463. io = (USHORT)port;
  464. io >>= 8;
  465. io &= 0x000F;
  466. buffer[3] = (WCHAR)('0' + io);
  467. if ( io >= 0x000A )
  468. buffer[3] += (WCHAR)('A' - '9' - 1);
  469. io = (USHORT)port;
  470. io >>= 4;
  471. io &= 0x000F;
  472. buffer[4] = (WCHAR)('0' + io);
  473. if ( io >= 0x000A )
  474. buffer[4] += (WCHAR)('A' - '9' - 1);
  475. io = (USHORT)port;
  476. io &= 0x000F;
  477. buffer[5] = (WCHAR)('0' + io);
  478. if ( io >= 0x000A )
  479. buffer[5] += (WCHAR)('A' - '9' - 1);
  480. buffer[6] = (WCHAR)0;
  481. }