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.

3856 lines
114 KiB

  1. /*--------------------------------------------------------------------------
  2. *
  3. * Copyright (C) Cyclades Corporation, 2000-2001.
  4. * All rights reserved.
  5. *
  6. * Cyclades-Z Port Driver
  7. *
  8. * This file: cyzpnp.c
  9. *
  10. * Description: This module contains the code that handles the
  11. * plug and play IRPs for the Cyclades-Z Port driver.
  12. *
  13. * Notes: This code supports Windows 2000 and Windows XP,
  14. * x86 and IA64 processors.
  15. *
  16. * Complies with Cyclades SW Coding Standard rev 1.3.
  17. *
  18. *--------------------------------------------------------------------------
  19. */
  20. /*-------------------------------------------------------------------------
  21. *
  22. * Change History
  23. *
  24. *--------------------------------------------------------------------------
  25. * Initial implementation based on Microsoft sample code.
  26. *
  27. *--------------------------------------------------------------------------
  28. */
  29. #include "precomp.h"
  30. #define ALLF 0xffffffff
  31. static const PHYSICAL_ADDRESS CyzPhysicalZero = {0};
  32. #ifdef ALLOC_PRAGMA
  33. #pragma alloc_text(PAGESRP0, CyzCreateDevObj)
  34. #pragma alloc_text(PAGESRP0, CyzAddDevice)
  35. #pragma alloc_text(PAGESRP0, CyzPnpDispatch)
  36. #pragma alloc_text(PAGESRP0, CyzStartDevice)
  37. // REMOVED FANNY #pragma alloc_text(PAGESRP0, CyzFinishStartDevice)
  38. // REMOVED FANNY #pragma alloc_text(PAGESRP0, CyzGetPortInfo)
  39. #pragma alloc_text(PAGESRP0, CyzDoExternalNaming)
  40. #pragma alloc_text(PAGESRP0, CyzReportMaxBaudRate)
  41. // REMOVED FANNY. NOT CALLED.#pragma alloc_text(PAGESRP0, CyzControllerCallBack)
  42. // REMOVED FANNY #pragma alloc_text(PAGESRP0, CyzItemCallBack)
  43. #pragma alloc_text(PAGESRP0, CyzUndoExternalNaming)
  44. #endif // ALLOC_PRAGMA
  45. //
  46. // Instantiate the GUID
  47. //
  48. #if !defined(FAR)
  49. #define FAR
  50. #endif // !defined(FAR)
  51. #include <initguid.h>
  52. DEFINE_GUID(GUID_CLASS_COMPORT, 0x86e0d1e0L, 0x8089, 0x11d0, 0x9c, 0xe4, 0x08,
  53. 0x00, 0x3e, 0x30, 0x1f, 0x73);
  54. #if DBG
  55. UCHAR *CyzSystemCapString[] = {
  56. "PowerSystemUnspecified",
  57. "PowerSystemWorking",
  58. "PowerSystemSleeping1",
  59. "PowerSystemSleeping2",
  60. "PowerSystemSleeping3",
  61. "PowerSystemHibernate",
  62. "PowerSystemShutdown",
  63. "PowerSystemMaximum"
  64. };
  65. UCHAR *CyzDeviceCapString[] = {
  66. "PowerDeviceUnspecified",
  67. "PowerDeviceD0",
  68. "PowerDeviceD1",
  69. "PowerDeviceD2",
  70. "PowerDeviceD3",
  71. "PowerDeviceMaximum"
  72. };
  73. #endif // DBG
  74. NTSTATUS
  75. CyzSyncCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp,
  76. IN PKEVENT CyzSyncEvent)
  77. {
  78. KeSetEvent(CyzSyncEvent, IO_NO_INCREMENT, FALSE);
  79. return STATUS_MORE_PROCESSING_REQUIRED;
  80. }
  81. ULONG
  82. CyzCompareString(PWCHAR PString1, PWCHAR PString2, ULONG Count)
  83. {
  84. do {
  85. if (*PString1 || *PString2) {
  86. if (*PString1 != *PString2) {
  87. break;
  88. }
  89. PString1++;
  90. PString2++;
  91. Count--;
  92. } else {
  93. break;
  94. }
  95. } while (Count);
  96. return (Count);
  97. }
  98. NTSTATUS
  99. CyzCreateDevObj(IN PDRIVER_OBJECT DriverObject,
  100. IN PDEVICE_OBJECT PPdo,
  101. OUT PDEVICE_OBJECT *NewDeviceObject)
  102. /*++
  103. Routine Description:
  104. This routine will create and initialize a functional device object to
  105. be attached to a Cyclades-Z controller PDO.
  106. Arguments:
  107. DriverObject - a pointer to the driver object this is created under
  108. NewDeviceObject - a location to store the pointer to the new device object
  109. Return Value:
  110. STATUS_SUCCESS if everything was successful
  111. reason for failure otherwise
  112. --*/
  113. {
  114. UNICODE_STRING deviceObjName;
  115. PDEVICE_OBJECT deviceObject = NULL;
  116. PCYZ_DEVICE_EXTENSION pDevExt;
  117. NTSTATUS status = STATUS_SUCCESS;
  118. static ULONG currentInstance = 0;
  119. UNICODE_STRING instanceStr;
  120. WCHAR instanceNumberBuffer[20];
  121. ULONG busNumber = 0xFFFFFFFF;
  122. ULONG resultLength;
  123. WCHAR hwID[100];
  124. PWCHAR portNumberPtr;
  125. INTERFACE_TYPE interfaceType;
  126. ULONG numberToAppend;
  127. PAGED_CODE();
  128. CyzDbgPrintEx(CYZTRACECALLS, "Enter CyzCreateDevObj\n");
  129. // Get PCI slot number and port number to generate device name.
  130. status = IoGetDeviceProperty (PPdo,
  131. DevicePropertyBusNumber,
  132. sizeof(busNumber),
  133. &busNumber,
  134. &resultLength);
  135. if (!NT_SUCCESS (status)) {
  136. busNumber = 0xFFFFFFFF; // Just to make sure set it again
  137. //CyzLogError( DriverObject,NULL,CyzPhysicalZero,CyzPhysicalZero,0,0,0,0,
  138. // status,CYZ_UNABLE_TO_GET_BUS_NUMBER,0,NULL,0,NULL);
  139. CyzDbgPrintEx(CYZERRORS,"CyzCreateDevObj: IoGetDeviceProperty BusNumber "
  140. "failed (%x)\n",status);
  141. goto NoBusNumber;
  142. }
  143. status = IoGetDeviceProperty (PPdo,
  144. DevicePropertyHardwareID,
  145. sizeof(hwID),
  146. hwID,
  147. &resultLength);
  148. if (!NT_SUCCESS (status)) {
  149. CyzLogError( DriverObject,NULL,CyzPhysicalZero,CyzPhysicalZero,0,0,0,0,
  150. status,CYZ_UNABLE_TO_GET_HW_ID,0,NULL,0,NULL);
  151. CyzDbgPrintEx(CYZERRORS,"CyzCreateDevObj: IoGetDeviceProperty HardwareID "
  152. "failed (%x)\n",status);
  153. return status;
  154. }
  155. if (CyzCompareString(hwID,CYZPORT_PNP_ID_WSTR,sizeof(CYZPORT_PNP_ID_WSTR)/sizeof(WCHAR)-1)!=0) {
  156. CyzLogError( DriverObject,NULL,CyzPhysicalZero,CyzPhysicalZero,0,0,0,0,
  157. status,CYZ_BAD_HW_ID,0,NULL,0,NULL);
  158. CyzDbgPrintEx(CYZERRORS,"CyzCreateDevObj: Bad HardwareID: %ws\n",hwID);
  159. return STATUS_UNSUCCESSFUL;
  160. }
  161. portNumberPtr = hwID+sizeof(CYZPORT_PNP_ID_WSTR)/sizeof(WCHAR)-1;
  162. NoBusNumber:;
  163. //
  164. // Zero out allocated memory pointers so we know if they must be freed
  165. //
  166. RtlZeroMemory(&deviceObjName, sizeof(UNICODE_STRING));
  167. deviceObjName.MaximumLength = DEVICE_OBJECT_NAME_LENGTH * sizeof(WCHAR);
  168. deviceObjName.Buffer = ExAllocatePool(PagedPool, deviceObjName.MaximumLength
  169. + sizeof(WCHAR));
  170. //********************************************
  171. // Error Injection
  172. // if (deviceObjName.Buffer != NULL) {
  173. // ExFreePool(deviceObjName.Buffer);
  174. // }
  175. // deviceObjName.Buffer = NULL;
  176. //********************************************
  177. if (deviceObjName.Buffer == NULL) {
  178. CyzLogError(DriverObject, NULL, CyzPhysicalZero, CyzPhysicalZero,
  179. 0, 0, 0, 11, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  180. 0, NULL, 0, NULL);
  181. CyzDbgPrintEx(CYZERRORS,
  182. "Couldn't allocate memory for device name\n");
  183. return STATUS_INSUFFICIENT_RESOURCES; //STATUS_SUCCESS replaced in build 2128
  184. }
  185. RtlZeroMemory(deviceObjName.Buffer, deviceObjName.MaximumLength
  186. + sizeof(WCHAR));
  187. RtlAppendUnicodeToString(&deviceObjName, L"\\Device\\");
  188. if (busNumber == 0xFFFFFFFF) {
  189. numberToAppend = currentInstance++;
  190. } else {
  191. numberToAppend = busNumber;
  192. }
  193. RtlInitUnicodeString(&instanceStr, NULL);
  194. instanceStr.MaximumLength = sizeof(instanceNumberBuffer);
  195. instanceStr.Buffer = instanceNumberBuffer;
  196. RtlIntegerToUnicodeString(numberToAppend, 10, &instanceStr);
  197. if (busNumber == 0xFFFFFFFF) {
  198. // The device name is something like \Device\Cyzport1
  199. RtlAppendUnicodeToString(&deviceObjName, L"CyzPort");
  200. RtlAppendUnicodeStringToString(&deviceObjName, &instanceStr);
  201. } else {
  202. // The device name is something like \Device\Pci5Cyzport1
  203. RtlAppendUnicodeToString(&deviceObjName, L"Pci");
  204. RtlAppendUnicodeStringToString(&deviceObjName, &instanceStr);
  205. RtlAppendUnicodeToString(&deviceObjName, L"CyzPort");
  206. RtlAppendUnicodeToString(&deviceObjName,portNumberPtr);
  207. }
  208. //
  209. // Create the device object
  210. //
  211. status = IoCreateDevice(DriverObject, sizeof(CYZ_DEVICE_EXTENSION),
  212. &deviceObjName, FILE_DEVICE_SERIAL_PORT,
  213. FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject);
  214. if (!NT_SUCCESS(status)) {
  215. CyzLogError(DriverObject, NULL, CyzPhysicalZero, CyzPhysicalZero,
  216. 0, 0, 0, 0, STATUS_SUCCESS, CYZ_DEVICE_CREATION_FAILURE,
  217. 0, NULL, 0, NULL);
  218. CyzDbgPrintEx(CYZERRORS, "CyzAddDevice: Create device failed - %x "
  219. "\n", status);
  220. goto CyzCreateDevObjError;
  221. }
  222. ASSERT(deviceObject != NULL);
  223. //
  224. // The device object has a pointer to an area of non-paged
  225. // pool allocated for this device. This will be the device
  226. // extension. Zero it out.
  227. //
  228. pDevExt = deviceObject->DeviceExtension;
  229. RtlZeroMemory(pDevExt, sizeof(CYZ_DEVICE_EXTENSION));
  230. //
  231. // Initialize the count of IRP's pending
  232. //
  233. pDevExt->PendingIRPCnt = 1;
  234. //
  235. // Initialize the count of DPC's pending
  236. //
  237. pDevExt->DpcCount = 1;
  238. //
  239. // Allocate Pool and save the nt device name in the device extension.
  240. //
  241. pDevExt->DeviceName.Buffer =
  242. ExAllocatePool(PagedPool, deviceObjName.Length + sizeof(WCHAR));
  243. //******************************************
  244. // Error Injection
  245. // if (pDevExt->DeviceName.Buffer != NULL) {
  246. // ExFreePool(pDevExt->DeviceName.Buffer);
  247. // }
  248. // pDevExt->DeviceName.Buffer = NULL;
  249. //******************************************
  250. if (!pDevExt->DeviceName.Buffer) {
  251. CyzLogError(
  252. DriverObject,
  253. NULL,
  254. CyzPhysicalZero,
  255. CyzPhysicalZero,
  256. 0,
  257. 0,
  258. 0,
  259. 12,
  260. STATUS_SUCCESS,
  261. CYZ_INSUFFICIENT_RESOURCES,
  262. 0,
  263. NULL,
  264. 0,
  265. NULL
  266. );
  267. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for DeviceName\n");
  268. status = STATUS_INSUFFICIENT_RESOURCES;
  269. goto CyzCreateDevObjError;
  270. }
  271. pDevExt->DeviceName.MaximumLength = deviceObjName.Length
  272. + sizeof(WCHAR);
  273. //
  274. // Zero fill it.
  275. //
  276. RtlZeroMemory(pDevExt->DeviceName.Buffer,
  277. pDevExt->DeviceName.MaximumLength);
  278. RtlAppendUnicodeStringToString(&pDevExt->DeviceName, &deviceObjName);
  279. pDevExt->NtNameForPort.Buffer = ExAllocatePool(PagedPool,
  280. deviceObjName.MaximumLength);
  281. if (pDevExt->NtNameForPort.Buffer == NULL) {
  282. CyzLogError(
  283. DriverObject,
  284. NULL,
  285. CyzPhysicalZero,
  286. CyzPhysicalZero,
  287. 0,
  288. 0,
  289. 0,
  290. 13,
  291. STATUS_SUCCESS,
  292. CYZ_INSUFFICIENT_RESOURCES,
  293. 0,
  294. NULL,
  295. 0,
  296. NULL
  297. );
  298. CyzDbgPrintEx(CYZERRORS, "CyzAddDevice: Cannot allocate memory for "
  299. "NtName\n");
  300. status = STATUS_INSUFFICIENT_RESOURCES;
  301. goto CyzCreateDevObjError;
  302. }
  303. pDevExt->NtNameForPort.MaximumLength = deviceObjName.MaximumLength;
  304. RtlAppendUnicodeStringToString(&pDevExt->NtNameForPort,
  305. &deviceObjName);
  306. //
  307. // Set up the device extension.
  308. //
  309. pDevExt->DeviceIsOpened = FALSE;
  310. pDevExt->DeviceObject = deviceObject;
  311. pDevExt->DriverObject = DriverObject;
  312. pDevExt->PowerState = PowerDeviceD0;
  313. //TODO FANNY: ADD TxFifoAmount?
  314. //pDevExt->TxFifoAmount = driverDefaults.TxFIFODefault;
  315. //pDevExt->CreatedSymbolicLink = TRUE; Removed by Fanny
  316. pDevExt->OwnsPowerPolicy = TRUE;
  317. pDevExt->PciSlot = busNumber;
  318. //TODO FANNY: SEE LATER IF WE NEED THE LISTS TO HANDLE INTERRUPT
  319. // InitializeListHead(&pDevExt->CommonInterruptObject);
  320. // InitializeListHead(&pDevExt->TopLevelSharers);
  321. // InitializeListHead(&pDevExt->MultiportSiblings);
  322. InitializeListHead(&pDevExt->AllDevObjs);
  323. InitializeListHead(&pDevExt->ReadQueue);
  324. InitializeListHead(&pDevExt->WriteQueue);
  325. InitializeListHead(&pDevExt->MaskQueue);
  326. InitializeListHead(&pDevExt->PurgeQueue);
  327. InitializeListHead(&pDevExt->StalledIrpQueue);
  328. ExInitializeFastMutex(&pDevExt->OpenMutex);
  329. ExInitializeFastMutex(&pDevExt->CloseMutex);
  330. //
  331. // Initialize the spinlock associated with fields read (& set)
  332. // by IO Control functions and the flags spinlock.
  333. //
  334. KeInitializeSpinLock(&pDevExt->ControlLock);
  335. KeInitializeSpinLock(&pDevExt->FlagsLock);
  336. #ifdef POLL
  337. KeInitializeSpinLock(&pDevExt->PollLock); // Added to fix Modem Share test 53 freeze
  338. #endif
  339. KeInitializeEvent(&pDevExt->PendingIRPEvent, SynchronizationEvent, FALSE);
  340. KeInitializeEvent(&pDevExt->PendingDpcEvent, SynchronizationEvent, FALSE);
  341. KeInitializeEvent(&pDevExt->PowerD0Event, SynchronizationEvent, FALSE);
  342. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  343. *NewDeviceObject = deviceObject;
  344. ExFreePool(deviceObjName.Buffer);
  345. CyzDbgPrintEx(CYZTRACECALLS, "Leave CyzCreateDevObj\n");
  346. return STATUS_SUCCESS;
  347. CyzCreateDevObjError:
  348. CyzDbgPrintEx(CYZERRORS, "CyzCreateDevObj Error, Cleaning up\n");
  349. //
  350. // Free the allocated strings for the NT and symbolic names if they exist.
  351. //
  352. if (deviceObjName.Buffer != NULL) {
  353. ExFreePool(deviceObjName.Buffer);
  354. }
  355. if (deviceObject) {
  356. if (pDevExt->NtNameForPort.Buffer != NULL) {
  357. ExFreePool(pDevExt->NtNameForPort.Buffer);
  358. }
  359. if (pDevExt->DeviceName.Buffer != NULL) {
  360. ExFreePool(pDevExt->DeviceName.Buffer);
  361. }
  362. IoDeleteDevice(deviceObject);
  363. }
  364. *NewDeviceObject = NULL;
  365. CyzDbgPrintEx(CYZTRACECALLS, "Leave CyzCreateDevObj\n");
  366. return status;
  367. }
  368. NTSTATUS
  369. CyzAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PPdo)
  370. /*++
  371. Routine Description:
  372. This routine creates a functional device object for com ports in the
  373. system and attaches them to the physical device objects for the ports
  374. Arguments:
  375. DriverObject - a pointer to the object for this driver
  376. PPdo - a pointer to the PDO in the stack we need to attach to
  377. Return Value:
  378. status from device creation and initialization
  379. --*/
  380. {
  381. PDEVICE_OBJECT pNewDevObj = NULL;
  382. PDEVICE_OBJECT pLowerDevObj = NULL;
  383. NTSTATUS status;
  384. PCYZ_DEVICE_EXTENSION pDevExt;
  385. PAGED_CODE();
  386. CyzDbgPrintEx(CYZTRACECALLS, "Enter CyzAddDevice with PPdo 0x%x\n",
  387. PPdo);
  388. if (PPdo == NULL) {
  389. //
  390. // Return no more devices
  391. //
  392. CyzLogError(DriverObject, NULL, CyzPhysicalZero, CyzPhysicalZero,
  393. 0, 0, 0, 0, STATUS_SUCCESS, CYZ_NO_PHYSICAL_DEVICE_OBJECT,
  394. 0, NULL, 0, NULL);
  395. CyzDbgPrintEx(CYZERRORS, "CyzAddDevice: Enumeration request, "
  396. "returning NO_MORE_ENTRIES\n");
  397. return (STATUS_NO_MORE_ENTRIES);
  398. }
  399. //
  400. // create and initialize the new device object
  401. //
  402. status = CyzCreateDevObj(DriverObject, PPdo, &pNewDevObj);
  403. if (!NT_SUCCESS(status)) {
  404. CyzDbgPrintEx(CYZERRORS,
  405. "CyzAddDevice - error creating new devobj [%#08lx]\n",
  406. status);
  407. return status;
  408. }
  409. //
  410. // Layer our DO on top of the lower device object
  411. // The return value is a pointer to the device object to which the
  412. // DO is actually attached.
  413. //
  414. pLowerDevObj = IoAttachDeviceToDeviceStack(pNewDevObj, PPdo);
  415. //
  416. // No status. Do the best we can.
  417. //
  418. ASSERT(pLowerDevObj != NULL);
  419. pDevExt = pNewDevObj->DeviceExtension;
  420. pDevExt->LowerDeviceObject = pLowerDevObj;
  421. pDevExt->Pdo = PPdo;
  422. //
  423. // Specify that this driver only supports buffered IO. This basically
  424. // means that the IO system copies the users data to and from
  425. // system supplied buffers.
  426. //
  427. // Also specify that we are power pagable.
  428. //
  429. pNewDevObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
  430. CyzDbgPrintEx(CYZTRACECALLS, "Leave CyzAddDevice\n");
  431. return status;
  432. }
  433. NTSTATUS
  434. CyzPnpDispatch(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  435. /*++
  436. Routine Description:
  437. This is a dispatch routine for the IRPs that come to the driver with the
  438. IRP_MJ_PNP major code (plug-and-play IRPs).
  439. Arguments:
  440. PDevObj - Pointer to the device object for this device
  441. PIrp - Pointer to the IRP for the current request
  442. Return Value:
  443. The function value is the final status of the call
  444. --*/
  445. {
  446. PCYZ_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  447. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  448. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  449. NTSTATUS status;
  450. PDEVICE_CAPABILITIES pDevCaps;
  451. PAGED_CODE();
  452. if ((status = CyzIRPPrologue(PIrp, pDevExt)) != STATUS_SUCCESS) {
  453. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  454. return status;
  455. }
  456. switch (pIrpStack->MinorFunction) {
  457. case IRP_MN_QUERY_CAPABILITIES: {
  458. PKEVENT pQueryCapsEvent;
  459. SYSTEM_POWER_STATE cap;
  460. CyzDbgPrintEx(CYZPNPPOWER,
  461. "Got IRP_MN_QUERY_DEVICE_CAPABILITIES IRP\n");
  462. pQueryCapsEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  463. if (pQueryCapsEvent == NULL) {
  464. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  465. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  466. return STATUS_INSUFFICIENT_RESOURCES;
  467. }
  468. KeInitializeEvent(pQueryCapsEvent, SynchronizationEvent, FALSE);
  469. IoCopyCurrentIrpStackLocationToNext(PIrp);
  470. IoSetCompletionRoutine(PIrp, CyzSyncCompletion, pQueryCapsEvent,
  471. TRUE, TRUE, TRUE);
  472. status = IoCallDriver(pLowerDevObj, PIrp);
  473. //
  474. // Wait for lower drivers to be done with the Irp
  475. //
  476. if (status == STATUS_PENDING) {
  477. KeWaitForSingleObject(pQueryCapsEvent, Executive, KernelMode, FALSE,
  478. NULL);
  479. }
  480. ExFreePool(pQueryCapsEvent);
  481. status = PIrp->IoStatus.Status;
  482. if (pIrpStack->Parameters.DeviceCapabilities.Capabilities == NULL) {
  483. goto errQueryCaps;
  484. }
  485. //
  486. // Save off their power capabilities
  487. //
  488. CyzDbgPrintEx(CYZPNPPOWER, "Mapping power capabilities\n");
  489. pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  490. pDevCaps = pIrpStack->Parameters.DeviceCapabilities.Capabilities;
  491. for (cap = PowerSystemSleeping1; cap < PowerSystemMaximum;
  492. cap++) {
  493. #if DBG
  494. CyzDbgPrintEx(CYZPNPPOWER, " %d: %s <--> %s\n",
  495. cap, CyzSystemCapString[cap],
  496. CyzDeviceCapString[pDevCaps->DeviceState[cap]]);
  497. #endif
  498. pDevExt->DeviceStateMap[cap] = pDevCaps->DeviceState[cap];
  499. }
  500. pDevExt->DeviceStateMap[PowerSystemUnspecified]
  501. = PowerDeviceUnspecified;
  502. pDevExt->DeviceStateMap[PowerSystemWorking]
  503. = PowerDeviceD0;
  504. pDevExt->SystemWake = pDevCaps->SystemWake;
  505. pDevExt->DeviceWake = pDevCaps->DeviceWake;
  506. errQueryCaps:;
  507. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  508. return status;
  509. }
  510. case IRP_MN_QUERY_DEVICE_RELATIONS:
  511. //
  512. // We just pass this down -- serenum enumerates our bus for us.
  513. //
  514. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_QUERY_DEVICE_RELATIONS Irp\n");
  515. switch (pIrpStack->Parameters.QueryDeviceRelations.Type) {
  516. case BusRelations:
  517. CyzDbgPrintEx(CYZPNPPOWER, "------- BusRelations Query\n");
  518. break;
  519. case EjectionRelations:
  520. CyzDbgPrintEx(CYZPNPPOWER, "------- EjectionRelations Query\n");
  521. break;
  522. case PowerRelations:
  523. CyzDbgPrintEx(CYZPNPPOWER, "------- PowerRelations Query\n");
  524. break;
  525. case RemovalRelations:
  526. CyzDbgPrintEx(CYZPNPPOWER, "------- RemovalRelations Query\n");
  527. break;
  528. case TargetDeviceRelation:
  529. CyzDbgPrintEx(CYZPNPPOWER, "------- TargetDeviceRelation Query\n");
  530. break;
  531. default:
  532. CyzDbgPrintEx(CYZPNPPOWER, "------- Unknown Query\n");
  533. break;
  534. }
  535. IoSkipCurrentIrpStackLocation(PIrp);
  536. status = CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  537. return status;
  538. case IRP_MN_QUERY_INTERFACE:
  539. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_QUERY_INTERFACE Irp\n");
  540. break;
  541. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  542. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_QUERY_RESOURCE_REQUIREMENTS Irp"
  543. "\n");
  544. break;
  545. case IRP_MN_START_DEVICE: {
  546. PVOID startLockPtr;
  547. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_START_DEVICE Irp\n");
  548. //
  549. // CyzStartDevice will pass this Irp to the next driver,
  550. // and process it as completion so just complete it here.
  551. //
  552. CyzLockPagableSectionByHandle(CyzGlobals.PAGESER_Handle);
  553. //
  554. // We used to make sure the stack was powered up, but now it
  555. // is supposed to be done implicitly by start_device.
  556. // If that wasn't the case we would just make this call:
  557. //
  558. //status = CyzGotoPowerState(PDevObj, pDevExt, PowerDeviceD0);
  559. pDevExt->PowerState = PowerDeviceD0;
  560. status = CyzStartDevice(PDevObj, PIrp);
  561. (void)CyzGotoPowerState(PDevObj, pDevExt, PowerDeviceD3);
  562. CyzUnlockPagableImageSection(CyzGlobals.PAGESER_Handle);
  563. PIrp->IoStatus.Status = status;
  564. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  565. return status;
  566. }
  567. case IRP_MN_READ_CONFIG:
  568. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_READ_CONFIG Irp\n");
  569. break;
  570. case IRP_MN_WRITE_CONFIG:
  571. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_WRITE_CONFIG Irp\n");
  572. break;
  573. case IRP_MN_EJECT:
  574. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_EJECT Irp\n");
  575. break;
  576. case IRP_MN_SET_LOCK:
  577. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_SET_LOCK Irp\n");
  578. break;
  579. case IRP_MN_QUERY_ID: {
  580. UNICODE_STRING pIdBuf;
  581. PWCHAR pPnpIdStr;
  582. ULONG pnpIdStrLen;
  583. ULONG portIndex = 0;
  584. HANDLE pnpKey;
  585. WCHAR WideString[MAX_DEVICE_ID_LEN];
  586. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_QUERY_ID Irp\n");
  587. // change from build 1946 to 2000.
  588. if (pIrpStack->Parameters.QueryId.IdType != BusQueryHardwareIDs
  589. && pIrpStack->Parameters.QueryId.IdType != BusQueryCompatibleIDs) {
  590. IoSkipCurrentIrpStackLocation(PIrp);
  591. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  592. }
  593. if (pIrpStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) {
  594. PIrp->IoStatus.Status = STATUS_SUCCESS;
  595. IoSkipCurrentIrpStackLocation(PIrp);
  596. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  597. }
  598. status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  599. STANDARD_RIGHTS_WRITE, &pnpKey);
  600. if (!NT_SUCCESS(status)) {
  601. PIrp->IoStatus.Status = status;
  602. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  603. return status;
  604. }
  605. status = CyzGetRegistryKeyValue (pnpKey, L"PortIndex",
  606. sizeof(L"PortIndex"),
  607. &portIndex,
  608. sizeof (ULONG));
  609. ZwClose(pnpKey);
  610. if (!NT_SUCCESS(status)) {
  611. PIrp->IoStatus.Status = status;
  612. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  613. return status;
  614. }
  615. // pPnpIdStr = isMulti ? SERIAL_PNP_MULTI_ID_STR : SERIAL_PNP_ID_STR;
  616. // pnpIdStrLen = isMulti ? sizeof(SERIAL_PNP_MULTI_ID_STR)
  617. // : sizeof(SERIAL_PNP_ID_STR);
  618. pnpIdStrLen = swprintf(WideString,L"%s%u",CYZPORT_PNP_ID_WSTR,portIndex+1);
  619. pnpIdStrLen = pnpIdStrLen * sizeof(WCHAR) + sizeof(UNICODE_NULL);
  620. pPnpIdStr = WideString;
  621. if (PIrp->IoStatus.Information != 0) {
  622. ULONG curStrLen;
  623. ULONG allocLen = 0;
  624. PWSTR curStr = (PWSTR)PIrp->IoStatus.Information;
  625. //
  626. // We have to walk the strings to count the amount of space to
  627. // reallocate
  628. //
  629. while ((curStrLen = wcslen(curStr)) != 0) {
  630. allocLen += curStrLen * sizeof(WCHAR) + sizeof(UNICODE_NULL);
  631. curStr += curStrLen + 1;
  632. }
  633. allocLen += sizeof(UNICODE_NULL);
  634. pIdBuf.Buffer = ExAllocatePool(PagedPool, allocLen
  635. + pnpIdStrLen
  636. + sizeof(WCHAR));
  637. if (pIdBuf.Buffer == NULL) {
  638. //
  639. // Clean up after other drivers since we are
  640. // sending the irp back up.
  641. //
  642. ExFreePool((PWSTR)PIrp->IoStatus.Information);
  643. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  644. PIrp->IoStatus.Information = 0;
  645. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  646. return STATUS_INSUFFICIENT_RESOURCES;
  647. }
  648. pIdBuf.MaximumLength = (USHORT)(allocLen + pnpIdStrLen);
  649. pIdBuf.Length = (USHORT)allocLen - sizeof(UNICODE_NULL);
  650. RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR));
  651. RtlCopyMemory(pIdBuf.Buffer, (PWSTR)PIrp->IoStatus.Information,
  652. allocLen);
  653. RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);
  654. //
  655. // Free what the previous driver allocated
  656. //
  657. ExFreePool((PWSTR)PIrp->IoStatus.Information);
  658. } else {
  659. CyzDbgPrintEx(CYZPNPPOWER, "ID is sole ID\n");
  660. pIdBuf.Buffer = ExAllocatePool(PagedPool, pnpIdStrLen
  661. + sizeof(WCHAR) * 2);
  662. if (pIdBuf.Buffer == NULL) {
  663. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  664. PIrp->IoStatus.Information = 0;
  665. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  666. return STATUS_INSUFFICIENT_RESOURCES;
  667. }
  668. pIdBuf.MaximumLength = (USHORT)pnpIdStrLen;
  669. pIdBuf.Length = 0;
  670. RtlZeroMemory(pIdBuf.Buffer, pIdBuf.MaximumLength + sizeof(WCHAR)
  671. * 2);
  672. RtlAppendUnicodeToString(&pIdBuf, pPnpIdStr);
  673. }
  674. PIrp->IoStatus.Information = (ULONG_PTR)pIdBuf.Buffer;
  675. PIrp->IoStatus.Status = STATUS_SUCCESS;
  676. IoCopyCurrentIrpStackLocationToNext(PIrp);
  677. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  678. }
  679. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: {
  680. HANDLE pnpKey;
  681. PKEVENT pResFiltEvent;
  682. ULONG isMulti = 0;
  683. PIO_RESOURCE_REQUIREMENTS_LIST pReqList;
  684. PIO_RESOURCE_LIST pResList;
  685. PIO_RESOURCE_DESCRIPTOR pResDesc;
  686. ULONG i, j;
  687. ULONG reqCnt;
  688. ULONG gotRuntime;
  689. ULONG gotMemory;
  690. ULONG gotInt;
  691. ULONG listNum;
  692. CyzDbgPrintEx(CYZPNPPOWER, "Got "
  693. "IRP_MN_FILTER_RESOURCE_REQUIREMENTS Irp\n");
  694. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  695. pResFiltEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  696. if (pResFiltEvent == NULL) {
  697. PIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  698. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  699. return STATUS_INSUFFICIENT_RESOURCES;
  700. }
  701. KeInitializeEvent(pResFiltEvent, SynchronizationEvent, FALSE);
  702. IoCopyCurrentIrpStackLocationToNext(PIrp);
  703. IoSetCompletionRoutine(PIrp, CyzSyncCompletion, pResFiltEvent,
  704. TRUE, TRUE, TRUE);
  705. status = IoCallDriver(pLowerDevObj, PIrp);
  706. //
  707. // Wait for lower drivers to be done with the Irp
  708. //
  709. if (status == STATUS_PENDING) {
  710. KeWaitForSingleObject (pResFiltEvent, Executive, KernelMode, FALSE,
  711. NULL);
  712. }
  713. ExFreePool(pResFiltEvent);
  714. if (PIrp->IoStatus.Information == 0) {
  715. if (pIrpStack->Parameters.FilterResourceRequirements
  716. .IoResourceRequirementList == 0) {
  717. CyzDbgPrintEx(CYZPNPPOWER, "Can't filter NULL resources!\n");
  718. status = PIrp->IoStatus.Status;
  719. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  720. return status;
  721. }
  722. PIrp->IoStatus.Information = (ULONG_PTR)pIrpStack->Parameters
  723. .FilterResourceRequirements
  724. .IoResourceRequirementList;
  725. }
  726. // REMOVED FANNY
  727. // status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  728. // STANDARD_RIGHTS_WRITE, &pnpKey);
  729. //
  730. // if (!NT_SUCCESS(status)) {
  731. // PIrp->IoStatus.Status = status;
  732. //
  733. // CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  734. // return status;
  735. //
  736. // }
  737. //
  738. // //
  739. // // No matter what we add our filter if we can and return success.
  740. // //
  741. //
  742. // status = CyzGetRegistryKeyValue (pnpKey, L"MultiportDevice",
  743. // sizeof(L"MultiportDevice"),
  744. // &isMulti,
  745. // sizeof (ULONG));
  746. //
  747. // ZwClose(pnpKey);
  748. //
  749. // Force ISR ports in IO_RES_REQ_LIST to shared status
  750. // Force interrupts to shared status
  751. //
  752. //
  753. // We will only process the first list -- multiport boards
  754. // should not have alternative resources
  755. //
  756. pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)PIrp->IoStatus.Information;
  757. pResList = &pReqList->List[0];
  758. CyzDbgPrintEx(CYZPNPPOWER, "List has %x lists (including "
  759. "alternatives)\n", pReqList->AlternativeLists);
  760. for (listNum = 0; listNum < (pReqList->AlternativeLists);
  761. listNum++) {
  762. gotRuntime = 0;
  763. gotMemory = 0;
  764. gotInt = 0;
  765. CyzDbgPrintEx(CYZPNPPOWER, "List has %x resources in it\n",
  766. pResList->Count);
  767. for (j = 0; (j < pResList->Count); j++) {
  768. pResDesc = &pResList->Descriptors[j];
  769. switch (pResDesc->Type) {
  770. case CmResourceTypeMemory:
  771. if (pResDesc->u.Memory.Length == CYZ_RUNTIME_LENGTH) {
  772. gotRuntime = 1;
  773. pResDesc->ShareDisposition = CmResourceShareShared;
  774. //TODO FANNY: Which should be the ShareDisposition for Y?
  775. //pResDesc->ShareDisposition = CmResourceShareDriverExclusive;
  776. CyzDbgPrintEx(CYZPNPPOWER, "Sharing Runtime Memory for "
  777. "device %x\n", pLowerDevObj);
  778. } else {
  779. gotMemory = 1;
  780. pResDesc->ShareDisposition = CmResourceShareShared;
  781. //TODO FANNY: Which should be the ShareDisposition for Y?
  782. //pResDesc->ShareDisposition = CmResourceShareDriverExclusive;
  783. CyzDbgPrintEx(CYZPNPPOWER, "Sharing Board Memory for "
  784. "device %x\n", pLowerDevObj);
  785. }
  786. break;
  787. case CmResourceTypePort:
  788. CyzDbgPrintEx(CYZPNPPOWER, "We should not have Port resource\n");
  789. break;
  790. case CmResourceTypeInterrupt:
  791. #ifndef POLL
  792. gotInt = 1;
  793. #endif
  794. pResDesc->ShareDisposition = CmResourceShareShared;
  795. CyzDbgPrintEx(CYZPNPPOWER, "Sharing interrupt "
  796. "for device %x\n",
  797. pLowerDevObj);
  798. break;
  799. default:
  800. break;
  801. }
  802. //
  803. // If we found what we need, we can break out of the loop
  804. //
  805. if (gotRuntime && gotMemory
  806. #ifndef POLL
  807. && gotInt
  808. #endif
  809. ) {
  810. break;
  811. }
  812. }
  813. pResList = (PIO_RESOURCE_LIST)((PUCHAR)pResList
  814. + sizeof(IO_RESOURCE_LIST)
  815. + sizeof(IO_RESOURCE_DESCRIPTOR)
  816. * (pResList->Count - 1));
  817. }
  818. PIrp->IoStatus.Status = STATUS_SUCCESS;
  819. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  820. return STATUS_SUCCESS;
  821. }
  822. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  823. {
  824. if (pDevExt->Flags & CYZ_FLAGS_BROKENHW) {
  825. (PNP_DEVICE_STATE)PIrp->IoStatus.Information |= PNP_DEVICE_FAILED;
  826. PIrp->IoStatus.Status = STATUS_SUCCESS;
  827. }
  828. IoCopyCurrentIrpStackLocationToNext(PIrp);
  829. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  830. }
  831. case IRP_MN_STOP_DEVICE:
  832. {
  833. ULONG pendingIRPs;
  834. KIRQL oldIrql;
  835. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_STOP_DEVICE Irp\n");
  836. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  837. //REMOVED FANNY FOR NOW
  838. // ASSERT(!pDevExt->PortOnAMultiportCard);
  839. CyzSetFlags(pDevExt, CYZ_FLAGS_STOPPED);
  840. CyzSetAccept(pDevExt,CYZ_PNPACCEPT_STOPPED);
  841. CyzClearAccept(pDevExt, CYZ_PNPACCEPT_STOPPING);
  842. pDevExt->PNPState = CYZ_PNP_STOPPING;
  843. //
  844. // From this point on all non-PNP IRP's will be queued
  845. //
  846. //
  847. // Decrement for entry here
  848. //
  849. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  850. //
  851. // Decrement for stopping
  852. //
  853. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  854. if (pendingIRPs) {
  855. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  856. KernelMode, FALSE, NULL);
  857. }
  858. //
  859. // Re-increment the count for later
  860. //
  861. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  862. //
  863. // We need to free resources...basically this is a remove
  864. // without the detach from the stack.
  865. //
  866. if (pDevExt->Flags & CYZ_FLAGS_STARTED) {
  867. CyzReleaseResources(pDevExt);
  868. }
  869. //
  870. // Pass the irp down
  871. //
  872. PIrp->IoStatus.Status = STATUS_SUCCESS;
  873. IoSkipCurrentIrpStackLocation(PIrp);
  874. return IoCallDriver(pLowerDevObj, PIrp);
  875. }
  876. case IRP_MN_QUERY_STOP_DEVICE:
  877. {
  878. KIRQL oldIrql;
  879. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_QUERY_STOP_DEVICE Irp\n");
  880. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  881. //
  882. // See if we should succeed a stop query
  883. //
  884. // REMOVED FANNY FOR NOW
  885. // if (pDevExt->PortOnAMultiportCard) {
  886. // PIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  887. // CyzDbgPrintEx(CYZPNPPOWER, "------- failing; multiport node\n");
  888. // CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  889. // return STATUS_NOT_SUPPORTED;
  890. // }
  891. //
  892. // If the device hasn't started yet, we ignore this request
  893. // and just pass it down.
  894. //
  895. if (pDevExt->PNPState != CYZ_PNP_STARTED) {
  896. IoSkipCurrentIrpStackLocation(PIrp);
  897. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  898. }
  899. //
  900. // Lock around the open status
  901. //
  902. ExAcquireFastMutex(&pDevExt->OpenMutex);
  903. if (pDevExt->DeviceIsOpened) {
  904. ExReleaseFastMutex(&pDevExt->OpenMutex);
  905. PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
  906. CyzDbgPrintEx(CYZPNPPOWER, "failing; device open\n");
  907. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  908. return STATUS_DEVICE_BUSY;
  909. }
  910. pDevExt->PNPState = CYZ_PNP_QSTOP;
  911. CyzSetAccept(pDevExt, CYZ_PNPACCEPT_STOPPING);
  912. //
  913. // Unlock around the open status
  914. //
  915. ExReleaseFastMutex(&pDevExt->OpenMutex);
  916. PIrp->IoStatus.Status = STATUS_SUCCESS;
  917. IoCopyCurrentIrpStackLocationToNext(PIrp);
  918. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  919. }
  920. case IRP_MN_CANCEL_STOP_DEVICE:
  921. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_CANCEL_STOP_DEVICE Irp\n");
  922. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  923. if (pDevExt->PNPState == CYZ_PNP_QSTOP) {
  924. //
  925. // Restore the device state
  926. //
  927. pDevExt->PNPState = CYZ_PNP_STARTED;
  928. CyzClearAccept(pDevExt, CYZ_PNPACCEPT_STOPPING);
  929. }
  930. PIrp->IoStatus.Status = STATUS_SUCCESS;
  931. IoCopyCurrentIrpStackLocationToNext(PIrp);
  932. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  933. case IRP_MN_CANCEL_REMOVE_DEVICE:
  934. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_CANCEL_REMOVE_DEVICE Irp\n");
  935. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  936. //
  937. // Restore the device state
  938. //
  939. pDevExt->PNPState = CYZ_PNP_STARTED;
  940. CyzClearAccept(pDevExt, CYZ_PNPACCEPT_REMOVING);
  941. PIrp->IoStatus.Status = STATUS_SUCCESS;
  942. IoCopyCurrentIrpStackLocationToNext(PIrp);
  943. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  944. case IRP_MN_QUERY_REMOVE_DEVICE:
  945. {
  946. KIRQL oldIrql;
  947. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_QUERY_REMOVE_DEVICE Irp\n");
  948. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  949. ExAcquireFastMutex(&pDevExt->OpenMutex);
  950. //
  951. // See if we should succeed a remove query
  952. //
  953. if (pDevExt->DeviceIsOpened) {
  954. ExReleaseFastMutex(&pDevExt->OpenMutex);
  955. PIrp->IoStatus.Status = STATUS_DEVICE_BUSY;
  956. CyzDbgPrintEx(CYZPNPPOWER, "failing; device open\n");
  957. CyzCompleteRequest(pDevExt, PIrp, IO_NO_INCREMENT);
  958. return STATUS_DEVICE_BUSY;
  959. }
  960. pDevExt->PNPState = CYZ_PNP_QREMOVE;
  961. CyzSetAccept(pDevExt, CYZ_PNPACCEPT_REMOVING);
  962. ExReleaseFastMutex(&pDevExt->OpenMutex);
  963. PIrp->IoStatus.Status = STATUS_SUCCESS;
  964. IoCopyCurrentIrpStackLocationToNext(PIrp);
  965. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  966. }
  967. case IRP_MN_SURPRISE_REMOVAL:
  968. {
  969. ULONG pendingIRPs;
  970. KIRQL oldIrql;
  971. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_SURPRISE_REMOVAL Irp\n");
  972. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  973. //
  974. // Prevent any new I/O to the device
  975. //
  976. CyzSetAccept(pDevExt, CYZ_PNPACCEPT_SURPRISE_REMOVING);
  977. //
  978. // Dismiss all pending requests
  979. //
  980. CyzKillPendingIrps(PDevObj);
  981. //
  982. // Wait for any pending requests we raced on.
  983. //
  984. //
  985. // Decrement once for ourselves
  986. //
  987. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  988. //
  989. // Decrement for the remove
  990. //
  991. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  992. if (pendingIRPs) {
  993. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  994. KernelMode, FALSE, NULL);
  995. }
  996. //
  997. // Reset for subsequent remove
  998. //
  999. InterlockedIncrement(&pDevExt->PendingIRPCnt);
  1000. //
  1001. // Remove any external interfaces and release resources
  1002. //
  1003. CyzDisableInterfacesResources(PDevObj, FALSE);
  1004. PIrp->IoStatus.Status = STATUS_SUCCESS;
  1005. IoSkipCurrentIrpStackLocation(PIrp);
  1006. return CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1007. }
  1008. case IRP_MN_REMOVE_DEVICE:
  1009. {
  1010. ULONG pendingIRPs;
  1011. KIRQL oldIrql;
  1012. CyzDbgPrintEx(CYZPNPPOWER, "Got IRP_MN_REMOVE_DEVICE Irp\n");
  1013. CyzDbgPrintEx(CYZPNPPOWER, "for device %x\n", pLowerDevObj);
  1014. //
  1015. // If we get this, we have to remove
  1016. //
  1017. //
  1018. // Mark as not accepting requests
  1019. //
  1020. CyzSetAccept(pDevExt, CYZ_PNPACCEPT_REMOVING);
  1021. //
  1022. // Complete all pending requests
  1023. //
  1024. CyzKillPendingIrps(PDevObj);
  1025. //
  1026. // Decrement for this Irp itself
  1027. //
  1028. InterlockedDecrement(&pDevExt->PendingIRPCnt);
  1029. //
  1030. // Wait for any pending requests we raced on -- this decrement
  1031. // is for our "placeholder".
  1032. //
  1033. pendingIRPs = InterlockedDecrement(&pDevExt->PendingIRPCnt);
  1034. if (pendingIRPs) {
  1035. KeWaitForSingleObject(&pDevExt->PendingIRPEvent, Executive,
  1036. KernelMode, FALSE, NULL);
  1037. }
  1038. if (!(pDevExt->DevicePNPAccept & CYZ_PNPACCEPT_SURPRISE_REMOVING)) { //Moved from CyzRemoveDevObj. Fanny
  1039. //
  1040. // Disable all external interfaces and release resources
  1041. //
  1042. CyzDisableInterfacesResources(PDevObj, TRUE);
  1043. }
  1044. //
  1045. // Pass the irp down
  1046. //
  1047. PIrp->IoStatus.Status = STATUS_SUCCESS;
  1048. IoSkipCurrentIrpStackLocation(PIrp); // It was IoCopyCurrentIrpStackLocationToNext (Fanny)
  1049. //
  1050. // We do decrement here because we incremented on entry here.
  1051. //
  1052. status = IoCallDriver(pLowerDevObj, PIrp);
  1053. //
  1054. // Remove us (Note from Fanny: This call is before IoCallDriver in serial driver).
  1055. //
  1056. CyzRemoveDevObj(PDevObj);
  1057. return status;
  1058. }
  1059. default:
  1060. break;
  1061. } // switch (pIrpStack->MinorFunction)
  1062. //
  1063. // Pass to driver beneath us
  1064. //
  1065. IoSkipCurrentIrpStackLocation(PIrp);
  1066. status = CyzIoCallDriver(pDevExt, pLowerDevObj, PIrp);
  1067. return status;
  1068. }
  1069. UINT32
  1070. CyzReportMaxBaudRate(ULONG Bauds)
  1071. /*++
  1072. Routine Description:
  1073. This routine returns the max baud rate given a selection of rates
  1074. Arguments:
  1075. Bauds - Bit-encoded list of supported bauds
  1076. Return Value:
  1077. The max baud rate listed in Bauds
  1078. --*/
  1079. {
  1080. PAGED_CODE();
  1081. if (Bauds & SERIAL_BAUD_128K) {
  1082. return (128U * 1024U);
  1083. }
  1084. if (Bauds & SERIAL_BAUD_115200) {
  1085. return 115200U;
  1086. }
  1087. if (Bauds & SERIAL_BAUD_56K) {
  1088. return (56U * 1024U);
  1089. }
  1090. if (Bauds & SERIAL_BAUD_57600) {
  1091. return 57600U;
  1092. }
  1093. if (Bauds & SERIAL_BAUD_38400) {
  1094. return 38400U;
  1095. }
  1096. if (Bauds & SERIAL_BAUD_19200) {
  1097. return 19200U;
  1098. }
  1099. if (Bauds & SERIAL_BAUD_14400) {
  1100. return 14400U;
  1101. }
  1102. if (Bauds & SERIAL_BAUD_9600) {
  1103. return 9600U;
  1104. }
  1105. if (Bauds & SERIAL_BAUD_7200) {
  1106. return 7200U;
  1107. }
  1108. if (Bauds & SERIAL_BAUD_4800) {
  1109. return 4800U;
  1110. }
  1111. if (Bauds & SERIAL_BAUD_2400) {
  1112. return 2400U;
  1113. }
  1114. if (Bauds & SERIAL_BAUD_1800) {
  1115. return 1800U;
  1116. }
  1117. if (Bauds & SERIAL_BAUD_1200) {
  1118. return 1200U;
  1119. }
  1120. if (Bauds & SERIAL_BAUD_600) {
  1121. return 600U;
  1122. }
  1123. if (Bauds & SERIAL_BAUD_300) {
  1124. return 300U;
  1125. }
  1126. if (Bauds & SERIAL_BAUD_150) {
  1127. return 150U;
  1128. }
  1129. if (Bauds & SERIAL_BAUD_134_5) {
  1130. return 135U; // Close enough
  1131. }
  1132. if (Bauds & SERIAL_BAUD_110) {
  1133. return 110U;
  1134. }
  1135. if (Bauds & SERIAL_BAUD_075) {
  1136. return 75U;
  1137. }
  1138. //
  1139. // We're in bad shape
  1140. //
  1141. return 0;
  1142. }
  1143. VOID
  1144. CyzAddToAllDevs(PLIST_ENTRY PListEntry)
  1145. {
  1146. KIRQL oldIrql;
  1147. KeAcquireSpinLock(&CyzGlobals.GlobalsSpinLock, &oldIrql);
  1148. InsertTailList(&CyzGlobals.AllDevObjs, PListEntry);
  1149. KeReleaseSpinLock(&CyzGlobals.GlobalsSpinLock, oldIrql);
  1150. }
  1151. NTSTATUS
  1152. CyzFinishStartDevice(IN PDEVICE_OBJECT PDevObj,
  1153. IN PCM_RESOURCE_LIST PResList,
  1154. IN PCM_RESOURCE_LIST PTrResList)
  1155. /*++
  1156. Routine Description:
  1157. This routine does serial-specific procedures to start a device. It
  1158. does this either for a legacy device detected by its registry entries,
  1159. or for a PnP device after the start IRP has been sent down the stack.
  1160. Arguments:
  1161. PDevObj - Pointer to the devobj that is starting
  1162. PResList - Pointer to the untranslated resources needed by this device
  1163. PTrResList - Pointer to the translated resources needed by this device
  1164. Return Value:
  1165. STATUS_SUCCESS on success, something else appropriate on failure
  1166. --*/
  1167. {
  1168. PCYZ_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1169. NTSTATUS status;
  1170. PCONFIG_DATA pConfig;
  1171. HANDLE pnpKey;
  1172. ULONG one = 1;
  1173. BOOLEAN allocedUserData = FALSE; // Added in build 2128
  1174. KIRQL oldIrql;
  1175. #ifdef POLL
  1176. KIRQL pollIrql;
  1177. #endif
  1178. PAGED_CODE();
  1179. //
  1180. // See if this is a restart, and if so don't reallocate the world
  1181. //
  1182. if ((pDevExt->Flags & CYZ_FLAGS_STOPPED)
  1183. && (pDevExt->Flags & CYZ_FLAGS_STARTED)) { // change from 1946 to 2000
  1184. CyzClearFlags(pDevExt, CYZ_FLAGS_STOPPED);
  1185. pDevExt->PNPState = CYZ_PNP_RESTARTING;
  1186. //
  1187. // Re-init resource-related things in the extension
  1188. //
  1189. #ifndef POLL
  1190. pDevExt->OurIsr = NULL;
  1191. pDevExt->OurIsrContext = NULL;
  1192. pDevExt->Interrupt = NULL;
  1193. pDevExt->Vector = 0;
  1194. pDevExt->Irql = 0;
  1195. pDevExt->OriginalVector = 0;
  1196. pDevExt->OriginalIrql = 0;
  1197. #endif
  1198. pDevExt->BusNumber = 0;
  1199. pDevExt->InterfaceType = 0;
  1200. #if 0
  1201. // removed for now - fanny
  1202. // pDevExt->TopLevelOurIsr = NULL;
  1203. // pDevExt->TopLevelOurIsrContext = NULL;
  1204. //
  1205. // pDevExt->OriginalController = CyzPhysicalZero;
  1206. // pDevExt->OriginalInterruptStatus = CyzPhysicalZero;
  1207. //
  1208. //
  1209. // pDevExt->Controller = NULL;
  1210. // pDevExt->InterruptStatus = NULL;
  1211. //
  1212. // pDevExt->SpanOfController = 0;
  1213. // pDevExt->SpanOfInterruptStatus = 0;
  1214. //
  1215. // pDevExt->Vector = 0;
  1216. // pDevExt->Irql = 0;
  1217. // pDevExt->OriginalVector = 0;
  1218. // pDevExt->OriginalIrql = 0;
  1219. // pDevExt->AddressSpace = 0;
  1220. // pDevExt->BusNumber = 0;
  1221. // pDevExt->InterfaceType = 0;
  1222. //
  1223. // pDevExt->CIsrSw = NULL;
  1224. //
  1225. // ASSERT(PUserData == NULL);
  1226. //
  1227. // PUserData = ExAllocatePool(PagedPool, sizeof(CYZ_USER_DATA));
  1228. //
  1229. // if (PUserData == NULL) {
  1230. // return STATUS_INSUFFICIENT_RESOURCES;
  1231. // }
  1232. //
  1233. // allocedUserData = TRUE; // Added in build 2128
  1234. //
  1235. // RtlZeroMemory(PUserData, sizeof(CYZ_USER_DATA));
  1236. //
  1237. // PUserData->DisablePort = FALSE;
  1238. // PUserData->UserClockRate = pDevExt->ClockRate;
  1239. // PUserData->TxFIFO = pDevExt->TxFifoAmount;
  1240. // PUserData->PermitShareDefault = pDevExt->PermitShare;
  1241. //
  1242. //
  1243. // //
  1244. // // Map betweeen trigger and amount
  1245. // //
  1246. //
  1247. // switch (pDevExt->RxFifoTrigger) {
  1248. // case CYZ_1_BYTE_HIGH_WATER:
  1249. // PUserData->RxFIFO = 1;
  1250. // break;
  1251. //
  1252. // case CYZ_4_BYTE_HIGH_WATER:
  1253. // PUserData->RxFIFO = 4;
  1254. // break;
  1255. //
  1256. // case CYZ_8_BYTE_HIGH_WATER:
  1257. // PUserData->RxFIFO = 8;
  1258. // break;
  1259. //
  1260. // case CYZ_14_BYTE_HIGH_WATER:
  1261. // PUserData->RxFIFO = 14;
  1262. // break;
  1263. //
  1264. // default:
  1265. // PUserData->RxFIFO = 1;
  1266. // }
  1267. #endif // end removal of code
  1268. } else {
  1269. //
  1270. // Mark as serenumerable -- toss status because we can
  1271. // still start without this key.
  1272. //
  1273. status = IoOpenDeviceRegistryKey(pDevExt->Pdo,
  1274. PLUGPLAY_REGKEY_DEVICE,
  1275. STANDARD_RIGHTS_WRITE, &pnpKey);
  1276. if (NT_SUCCESS(status)) {
  1277. ULONG powerPolicy = 0;
  1278. //
  1279. // Find out if we own power policy
  1280. //
  1281. CyzGetRegistryKeyValue(pnpKey, L"CyzRelinquishPowerPolicy",
  1282. sizeof(L"CyzRelinquishPowerPolicy"),
  1283. &powerPolicy, sizeof(ULONG));
  1284. pDevExt->OwnsPowerPolicy = powerPolicy ? FALSE : TRUE;
  1285. ZwClose(pnpKey);
  1286. }
  1287. }
  1288. //
  1289. // Allocate the config record.
  1290. //
  1291. pConfig = ExAllocatePool (PagedPool, sizeof(CONFIG_DATA));
  1292. //************************************
  1293. // Error Injection
  1294. //if (pConfig) {
  1295. // ExFreePool (pConfig);
  1296. //}
  1297. //pConfig = NULL;
  1298. //************************************
  1299. if (pConfig == NULL) {
  1300. CyzLogError(pDevExt->DriverObject, NULL, CyzPhysicalZero,
  1301. CyzPhysicalZero, 0, 0, 0, 31, STATUS_SUCCESS,
  1302. CYZ_INSUFFICIENT_RESOURCES, 0, NULL, 0, NULL);
  1303. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for the\n"
  1304. "------ user configuration record\n");
  1305. status = STATUS_INSUFFICIENT_RESOURCES;
  1306. goto CyzFinishStartDeviceError;
  1307. }
  1308. RtlZeroMemory(pConfig, sizeof(CONFIG_DATA));
  1309. //
  1310. // Get the configuration info for the device.
  1311. //
  1312. status = CyzGetPortInfo(PDevObj, PResList, PTrResList, pConfig);
  1313. if (!NT_SUCCESS(status)) {
  1314. goto CyzFinishStartDeviceError;
  1315. }
  1316. //
  1317. // See if we are in the proper power state.
  1318. //
  1319. if (pDevExt->PowerState != PowerDeviceD0) {
  1320. status = CyzGotoPowerState(pDevExt->Pdo, pDevExt, PowerDeviceD0);
  1321. if (!NT_SUCCESS(status)) {
  1322. goto CyzFinishStartDeviceError;
  1323. }
  1324. }
  1325. //
  1326. // Find and initialize the controller
  1327. //
  1328. status = CyzFindInitController(PDevObj, pConfig);
  1329. if (!NT_SUCCESS(status)) {
  1330. goto CyzFinishStartDeviceError;
  1331. }
  1332. #ifndef POLL
  1333. //
  1334. // The hardware that is set up to NOT interrupt, connect an interrupt.
  1335. //
  1336. //
  1337. // If a device doesn't already have an interrupt and it has an isr then
  1338. // we attempt to connect to the interrupt if it is not shareing with other
  1339. // serial devices. If we fail to connect to an interrupt we will delete
  1340. // this device.
  1341. //
  1342. if (pDevExt != NULL) {
  1343. CyzDbgPrintEx(CYZDIAG5, "pDevExt: Interrupt %x\n"
  1344. "------- OurIsr %x\n", pDevExt->Interrupt,
  1345. pDevExt->OurIsr);
  1346. } else {
  1347. CyzDbgPrintEx(CYZERRORS, "CyzFinishStartDevice got NULL "
  1348. "pDevExt\n");
  1349. }
  1350. if ((!pDevExt->Interrupt) && (pDevExt->OurIsr)) {
  1351. CyzDbgPrintEx(CYZDIAG5,
  1352. "About to connect to interrupt for port %wZ\n"
  1353. "------- address of extension is %x\n",
  1354. &pDevExt->DeviceName, pDevExt);
  1355. CyzDbgPrintEx(CYZDIAG5, "IoConnectInterrupt Args:\n"
  1356. "Interrupt %x\n"
  1357. "OurIsr %x\n"
  1358. "OurIsrContext %x\n"
  1359. "NULL\n"
  1360. "Vector %x\n"
  1361. "Irql %x\n"
  1362. "InterruptMode %x\n"
  1363. "InterruptShareable %x\n"
  1364. "ProcessorAffinity %x\n"
  1365. "FALSE\n",
  1366. &pDevExt->Interrupt,
  1367. CyzIsr,
  1368. pDevExt->OurIsrContext,
  1369. pDevExt->Vector,
  1370. pDevExt->Irql,
  1371. pConfig->InterruptMode,
  1372. pDevExt->InterruptShareable,
  1373. pConfig->Affinity
  1374. );
  1375. //
  1376. // Do a just in time construction of the ISR switch.
  1377. //
  1378. //removed fanny
  1379. // pDevExt->CIsrSw->IsrFunc = pDevExt->OurIsr;
  1380. // pDevExt->CIsrSw->Context = pDevExt->OurIsrContext;
  1381. status = IoConnectInterrupt(&pDevExt->Interrupt, pDevExt->OurIsr,
  1382. pDevExt->OurIsrContext, NULL,
  1383. pDevExt->Vector, pDevExt->Irql,
  1384. pDevExt->Irql,
  1385. pConfig->InterruptMode,
  1386. pDevExt->InterruptShareable,
  1387. pConfig->Affinity, FALSE);
  1388. //****************************************
  1389. // Error Injection
  1390. // if (pDevExt->Interrupt != NULL) {
  1391. // IoDisconnectInterrupt(pDevExt->Interrupt);
  1392. // pDevExt->Interrupt = NULL;
  1393. // }
  1394. // status = STATUS_INSUFFICIENT_RESOURCES;
  1395. //****************************************
  1396. if (!NT_SUCCESS(status)) {
  1397. //
  1398. // Hmmm, how'd that happen? Somebody either
  1399. // didn't report their resources, or they
  1400. // sneaked in since the last time I looked.
  1401. //
  1402. // Oh well, delete this device.
  1403. //
  1404. CyzDbgPrintEx(CYZERRORS, "Couldn't connect to interrupt for %wZ\n",
  1405. &pDevExt->DeviceName);
  1406. CyzDbgPrintEx(CYZERRORS, "IoConnectInterrupt Args:\n"
  1407. "Interrupt %x\n"
  1408. "OurIsr %x\n"
  1409. "OurIsrContext %x\n"
  1410. "NULL\n"
  1411. "Vector %x\n"
  1412. "Irql %x\n"
  1413. "InterruptMode %x\n"
  1414. "InterruptShareable %x\n"
  1415. "ProcessorAffinity %x\n"
  1416. "FALSE\n",
  1417. &pDevExt->Interrupt,
  1418. CyzIsr,
  1419. pDevExt->OurIsrContext,
  1420. pDevExt->Vector,
  1421. pDevExt->Irql,
  1422. pConfig->InterruptMode,
  1423. pDevExt->InterruptShareable,
  1424. pConfig->Affinity);
  1425. CyzLogError(PDevObj->DriverObject, PDevObj,
  1426. pDevExt->OriginalBoardMemory,
  1427. CyzPhysicalZero, 0, 0, 0, pDevExt->Vector, status,
  1428. CYZ_UNREPORTED_IRQL_CONFLICT,
  1429. pDevExt->DeviceName.Length + sizeof(WCHAR),
  1430. pDevExt->DeviceName.Buffer, 0, NULL);
  1431. //status = CYZ_UNREPORTED_IRQL_CONFLICT; Originally, it was SERIAL_UNREPORTED_IRQL_CONFLICT.
  1432. goto CyzFinishStartDeviceError;
  1433. }
  1434. CyzDbgPrintEx(CYZDIAG5, "Connected interrupt %08X\n", pDevExt->Interrupt);
  1435. // This was the first interrupt connected. We can now enable
  1436. // the PCI interrupts. Let's keep the UART interrupts disabled
  1437. // until we have an Open.
  1438. {
  1439. ULONG intr_reg;
  1440. intr_reg = CYZ_READ_ULONG(&(pDevExt->Runtime)->intr_ctrl_stat);
  1441. //intr_reg |= (0x00030800UL);
  1442. intr_reg |= (0x00030B00UL);
  1443. CYZ_WRITE_ULONG(&(pDevExt->Runtime)->intr_ctrl_stat,intr_reg);
  1444. }
  1445. }
  1446. #endif
  1447. //
  1448. // Add the PDevObj to the master list
  1449. //
  1450. CyzAddToAllDevs(&pDevExt->AllDevObjs);
  1451. //
  1452. // Reset the device.
  1453. //
  1454. #ifndef POLL
  1455. //
  1456. // While the device isn't open, disable all interrupts.
  1457. //
  1458. CYZ_WRITE_ULONG(&(pDevExt->ChCtrl)->intr_enable,C_IN_DISABLE); //1.0.0.11
  1459. CyzIssueCmd(pDevExt,C_CM_IOCTL,0L,FALSE);
  1460. #endif
  1461. //
  1462. // This should set up everything as it should be when
  1463. // a device is to be opened. We do need to lower the
  1464. // modem lines, and disable the recalcitrant fifo
  1465. // so that it will show up if the user boots to dos.
  1466. //
  1467. #ifdef POLL
  1468. KeAcquireSpinLock(&pDevExt->PollLock, &pollIrql);
  1469. CyzReset(pDevExt);
  1470. CyzMarkClose(pDevExt);
  1471. CyzClrRTS(pDevExt);
  1472. CyzClrDTR(pDevExt);
  1473. KeReleaseSpinLock(&pDevExt->PollLock, pollIrql);
  1474. #else
  1475. KeSynchronizeExecution(
  1476. pDevExt->Interrupt,
  1477. CyzReset,
  1478. pDevExt
  1479. );
  1480. KeSynchronizeExecution( //Disables the fifo.
  1481. pDevExt->Interrupt,
  1482. CyzMarkClose,
  1483. pDevExt
  1484. );
  1485. KeSynchronizeExecution(
  1486. pDevExt->Interrupt,
  1487. CyzClrRTS,
  1488. pDevExt
  1489. );
  1490. KeSynchronizeExecution(
  1491. pDevExt->Interrupt,
  1492. CyzClrDTR,
  1493. pDevExt
  1494. );
  1495. #endif
  1496. if (pDevExt->PNPState == CYZ_PNP_ADDED ) {
  1497. //
  1498. // Do the external naming now that the device is accessible.
  1499. //
  1500. status = CyzDoExternalNaming(pDevExt, pDevExt->DeviceObject->
  1501. DriverObject);
  1502. if (!NT_SUCCESS(status)) {
  1503. CyzDbgPrintEx(CYZERRORS, "External Naming Failed - Status %x\n",
  1504. status);
  1505. //
  1506. // Allow the device to start anyhow
  1507. //
  1508. status = STATUS_SUCCESS;
  1509. }
  1510. } else {
  1511. CyzDbgPrintEx(CYZPNPPOWER, "Not doing external naming -- state is %x"
  1512. "\n", pDevExt->PNPState);
  1513. }
  1514. CyzFinishStartDeviceError:;
  1515. if (!NT_SUCCESS (status)) {
  1516. CyzDbgPrintEx(CYZDIAG1, "Cleaning up failed start\n");
  1517. //
  1518. // Resources created by this routine will be cleaned up by the remove
  1519. //
  1520. if (pDevExt->PNPState == CYZ_PNP_RESTARTING) {
  1521. //
  1522. // Kill all that lives and breathes -- we'll clean up the
  1523. // rest on the impending remove
  1524. //
  1525. CyzKillPendingIrps(PDevObj);
  1526. //
  1527. // In fact, pretend we're removing so we don't take any
  1528. // more irps
  1529. //
  1530. CyzSetAccept(pDevExt, CYZ_PNPACCEPT_REMOVING);
  1531. CyzClearFlags(pDevExt, CYZ_FLAGS_STARTED);
  1532. }
  1533. } else { // SUCCESS
  1534. //
  1535. // Fill in WMI hardware data
  1536. //
  1537. #ifndef POLL
  1538. pDevExt->WmiHwData.IrqNumber = pDevExt->Irql;
  1539. pDevExt->WmiHwData.IrqLevel = pDevExt->Irql;
  1540. pDevExt->WmiHwData.IrqVector = pDevExt->Vector;
  1541. pDevExt->WmiHwData.IrqAffinityMask = pConfig->Affinity;
  1542. pDevExt->WmiHwData.InterruptType = pConfig->InterruptMode == Latched
  1543. ? SERIAL_WMI_INTTYPE_LATCHED : SERIAL_WMI_INTTYPE_LEVEL;
  1544. pDevExt->WmiHwData.BaseIOAddress = (ULONG_PTR)pDevExt->BoardMemory;
  1545. #endif
  1546. //
  1547. // Fill in WMI device state data (as defaults)
  1548. //
  1549. pDevExt->WmiCommData.BaudRate = pDevExt->CurrentBaud;
  1550. switch(pDevExt->CommDataLen & C_DL_CS) {
  1551. case C_DL_CS5:
  1552. pDevExt->WmiCommData.BitsPerByte = 5;
  1553. break;
  1554. case C_DL_CS6:
  1555. pDevExt->WmiCommData.BitsPerByte = 6;
  1556. break;
  1557. case C_DL_CS7:
  1558. pDevExt->WmiCommData.BitsPerByte = 7;
  1559. break;
  1560. case C_DL_CS8:
  1561. pDevExt->WmiCommData.BitsPerByte = 8;
  1562. break;
  1563. }
  1564. pDevExt->WmiCommData.ParityCheckEnable = (pDevExt->CommParity & C_PR_PARITY)
  1565. ? TRUE : FALSE;
  1566. switch (pDevExt->CommParity & C_PR_PARITY) {
  1567. case C_PR_NONE:
  1568. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  1569. break;
  1570. case C_PR_ODD:
  1571. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_ODD;
  1572. break;
  1573. case C_PR_EVEN:
  1574. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_EVEN;
  1575. break;
  1576. case C_PR_MARK:
  1577. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_MARK;
  1578. break;
  1579. case C_PR_SPACE:
  1580. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_SPACE;
  1581. break;
  1582. default:
  1583. ASSERTMSG(0, "CYZPORT: Illegal Parity setting for WMI");
  1584. pDevExt->WmiCommData.Parity = SERIAL_WMI_PARITY_NONE;
  1585. break;
  1586. }
  1587. switch(pDevExt->CommDataLen & C_DL_STOP) {
  1588. case C_DL_1STOP:
  1589. pDevExt->WmiCommData.StopBits = SERIAL_WMI_STOP_1;
  1590. break;
  1591. case C_DL_15STOP:
  1592. pDevExt->WmiCommData.StopBits = SERIAL_WMI_STOP_1_5;
  1593. break;
  1594. case C_DL_2STOP:
  1595. pDevExt->WmiCommData.StopBits = SERIAL_WMI_STOP_2;
  1596. break;
  1597. default:
  1598. ASSERTMSG(0, "CYZPORT: Illegal Stop Bit setting for WMI");
  1599. pDevExt->WmiCommData.Parity = SERIAL_WMI_STOP_1;
  1600. break;
  1601. }
  1602. pDevExt->WmiCommData.XoffCharacter = pDevExt->SpecialChars.XoffChar;
  1603. pDevExt->WmiCommData.XoffXmitThreshold = pDevExt->HandFlow.XoffLimit;
  1604. pDevExt->WmiCommData.XonCharacter = pDevExt->SpecialChars.XonChar;
  1605. pDevExt->WmiCommData.XonXmitThreshold = pDevExt->HandFlow.XonLimit;
  1606. pDevExt->WmiCommData.MaximumBaudRate
  1607. = CyzReportMaxBaudRate(pDevExt->SupportedBauds);
  1608. pDevExt->WmiCommData.MaximumOutputBufferSize = (UINT32)((ULONG)-1);
  1609. pDevExt->WmiCommData.MaximumInputBufferSize = (UINT32)((ULONG)-1);
  1610. pDevExt->WmiCommData.Support16BitMode = FALSE;
  1611. pDevExt->WmiCommData.SupportDTRDSR = TRUE;
  1612. pDevExt->WmiCommData.SupportIntervalTimeouts = TRUE;
  1613. pDevExt->WmiCommData.SupportParityCheck = TRUE;
  1614. pDevExt->WmiCommData.SupportRTSCTS = TRUE;
  1615. pDevExt->WmiCommData.SupportXonXoff = TRUE;
  1616. pDevExt->WmiCommData.SettableBaudRate = TRUE;
  1617. pDevExt->WmiCommData.SettableDataBits = TRUE;
  1618. pDevExt->WmiCommData.SettableFlowControl = TRUE;
  1619. pDevExt->WmiCommData.SettableParity = TRUE;
  1620. pDevExt->WmiCommData.SettableParityCheck = TRUE;
  1621. pDevExt->WmiCommData.SettableStopBits = TRUE;
  1622. pDevExt->WmiCommData.IsBusy = FALSE;
  1623. //
  1624. // Fill in wmi perf data (all zero's)
  1625. //
  1626. RtlZeroMemory(&pDevExt->WmiPerfData, sizeof(pDevExt->WmiPerfData));
  1627. if (pDevExt->PNPState == CYZ_PNP_ADDED) {
  1628. PULONG countSoFar = &IoGetConfigurationInformation()->SerialCount;
  1629. (*countSoFar)++;
  1630. //
  1631. // Register for WMI
  1632. //
  1633. pDevExt->WmiLibInfo.GuidCount = sizeof(SerialWmiGuidList) /
  1634. sizeof(WMIGUIDREGINFO);
  1635. pDevExt->WmiLibInfo.GuidList = SerialWmiGuidList;
  1636. ASSERT (pDevExt->WmiLibInfo.GuidCount == SERIAL_WMI_GUID_LIST_SIZE);
  1637. pDevExt->WmiLibInfo.QueryWmiRegInfo = CyzQueryWmiRegInfo;
  1638. pDevExt->WmiLibInfo.QueryWmiDataBlock = CyzQueryWmiDataBlock;
  1639. pDevExt->WmiLibInfo.SetWmiDataBlock = CyzSetWmiDataBlock;
  1640. pDevExt->WmiLibInfo.SetWmiDataItem = CyzSetWmiDataItem;
  1641. pDevExt->WmiLibInfo.ExecuteWmiMethod = NULL;
  1642. pDevExt->WmiLibInfo.WmiFunctionControl = NULL;
  1643. IoWMIRegistrationControl(PDevObj, WMIREG_ACTION_REGISTER);
  1644. }
  1645. if (pDevExt->PNPState == CYZ_PNP_RESTARTING) {
  1646. //
  1647. // Release the stalled IRP's
  1648. //
  1649. CyzUnstallIrps(pDevExt);
  1650. }
  1651. pDevExt->PNPState = CYZ_PNP_STARTED;
  1652. CyzClearAccept(pDevExt, ~CYZ_PNPACCEPT_OK);
  1653. CyzSetFlags(pDevExt, CYZ_FLAGS_STARTED);
  1654. }
  1655. if (pConfig) {
  1656. ExFreePool (pConfig);
  1657. }
  1658. // REMOVED BY FANNY
  1659. // if ((PUserData != NULL)
  1660. // && (pDevExt->PNPState == CYZ_PNP_RESTARTING)) {
  1661. // ExFreePool(PUserData);
  1662. // }
  1663. #if 0
  1664. if ((PUserData != NULL) && allocedUserData) { // Added in build 2128
  1665. ExFreePool(PUserData);
  1666. }
  1667. #endif
  1668. CyzDbgPrintEx (CYZTRACECALLS, "leaving CyzFinishStartDevice\n");
  1669. return status;
  1670. }
  1671. NTSTATUS
  1672. CyzStartDevice(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp)
  1673. /*++
  1674. Routine Description:
  1675. This routine first passes the start device Irp down the stack then
  1676. it picks up the resources for the device, ititializes, puts it on any
  1677. appropriate lists (i.e shared interrupt or interrupt status) and
  1678. connects the interrupt.
  1679. Arguments:
  1680. PDevObj - Pointer to the device object for this device
  1681. PIrp - Pointer to the IRP for the current request
  1682. Return Value:
  1683. Return status
  1684. --*/
  1685. {
  1686. PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(PIrp);
  1687. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  1688. PCYZ_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1689. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  1690. // Next: variables to get resources from the Registry
  1691. HANDLE keyHandle;
  1692. ULONG dataLength;
  1693. PCM_RESOURCE_LIST portResources = NULL;
  1694. PCM_RESOURCE_LIST portResourcesTr = NULL;
  1695. PAGED_CODE();
  1696. CyzDbgPrintEx(CYZTRACECALLS, "entering CyzStartDevice\n");
  1697. //
  1698. // Pass this down to the next device object
  1699. //
  1700. KeInitializeEvent(&pDevExt->CyzStartEvent, SynchronizationEvent,
  1701. FALSE);
  1702. IoCopyCurrentIrpStackLocationToNext(PIrp);
  1703. IoSetCompletionRoutine(PIrp, CyzSyncCompletion,
  1704. &pDevExt->CyzStartEvent, TRUE, TRUE, TRUE);
  1705. status = IoCallDriver(pLowerDevObj, PIrp);
  1706. //
  1707. // Wait for lower drivers to be done with the Irp
  1708. //
  1709. if (status == STATUS_PENDING) {
  1710. KeWaitForSingleObject (&pDevExt->CyzStartEvent, Executive, KernelMode,
  1711. FALSE, NULL);
  1712. status = PIrp->IoStatus.Status;
  1713. }
  1714. //*********************************
  1715. // Error Injection
  1716. // status = STATUS_UNSUCCESSFUL;
  1717. //*********************************
  1718. if (!NT_SUCCESS(status)) {
  1719. CyzDbgPrintEx(CYZERRORS, "error with IoCallDriver %x\n", status);
  1720. CyzLogError( pDevExt->DriverObject,NULL,
  1721. CyzPhysicalZero,CyzPhysicalZero,
  1722. 0,0,0,0,status,CYZ_LOWER_DRIVERS_FAILED_START,
  1723. 0,NULL,0,NULL);
  1724. return status;
  1725. }
  1726. // Get resources from the registry
  1727. status = IoOpenDeviceRegistryKey (pDevExt->Pdo,
  1728. PLUGPLAY_REGKEY_DEVICE,
  1729. STANDARD_RIGHTS_READ,
  1730. &keyHandle);
  1731. if (!NT_SUCCESS(status)) {
  1732. CyzDbgPrintEx(CYZERRORS, "IoOpenDeviceRegistryKey failed - %x "
  1733. "\n", status);
  1734. } else {
  1735. dataLength = CyzGetRegistryKeyValueLength (keyHandle,
  1736. L"PortResources",
  1737. sizeof(L"PortResources"));
  1738. portResources = ExAllocatePool(PagedPool, dataLength);
  1739. if (portResources) {
  1740. status = CyzGetRegistryKeyValue (keyHandle, L"PortResources",
  1741. sizeof(L"PortResources"),
  1742. portResources,
  1743. dataLength);
  1744. if (!NT_SUCCESS(status)) {
  1745. CyzDbgPrintEx(CYZERRORS, "CyzGetRegistryKeyValue PortResources "
  1746. "failed - %x\n", status);
  1747. goto CyzStartDevice_End;
  1748. }
  1749. }
  1750. dataLength = CyzGetRegistryKeyValueLength (keyHandle,
  1751. L"PortResourcesTr",
  1752. sizeof(L"PortResourcesTr"));
  1753. portResourcesTr = ExAllocatePool(PagedPool, dataLength);
  1754. if (portResourcesTr) {
  1755. status = CyzGetRegistryKeyValue (keyHandle, L"PortResourcesTr",
  1756. sizeof(L"PortResourcesTr"),
  1757. portResourcesTr,
  1758. dataLength);
  1759. if (!NT_SUCCESS(status)) {
  1760. CyzDbgPrintEx(CYZERRORS, "CyzGetRegistryKeyValue PortResourcesTr "
  1761. "failed - %xn", status);
  1762. goto CyzStartDevice_End;
  1763. }
  1764. }
  1765. //
  1766. // Do the serial specific items to start the device
  1767. //
  1768. status = CyzFinishStartDevice(PDevObj, portResources, portResourcesTr);
  1769. CyzStartDevice_End:
  1770. if (portResources) {
  1771. ExFreePool(portResources);
  1772. }
  1773. if (portResourcesTr) {
  1774. ExFreePool(portResourcesTr);
  1775. }
  1776. ZwClose (keyHandle);
  1777. }
  1778. #if 0
  1779. //
  1780. // Do the serial specific items to start the device
  1781. //
  1782. status = CyzFinishStartDevice(PDevObj, pIrpStack->Parameters.StartDevice
  1783. .AllocatedResources,
  1784. pIrpStack->Parameters.StartDevice
  1785. .AllocatedResourcesTranslated);
  1786. #endif
  1787. return status;
  1788. }
  1789. NTSTATUS
  1790. CyzItemCallBack(
  1791. IN PVOID Context,
  1792. IN PUNICODE_STRING PathName,
  1793. IN INTERFACE_TYPE BusType,
  1794. IN ULONG BusNumber,
  1795. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  1796. IN CONFIGURATION_TYPE ControllerType,
  1797. IN ULONG ControllerNumber,
  1798. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  1799. IN CONFIGURATION_TYPE PeripheralType,
  1800. IN ULONG PeripheralNumber,
  1801. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. This routine is called to check if a particular item
  1806. is present in the registry.
  1807. Arguments:
  1808. Context - Pointer to a boolean.
  1809. PathName - unicode registry path. Not Used.
  1810. BusType - Internal, Isa, ...
  1811. BusNumber - Which bus if we are on a multibus system.
  1812. BusInformation - Configuration information about the bus. Not Used.
  1813. ControllerType - Controller type.
  1814. ControllerNumber - Which controller if there is more than one
  1815. controller in the system.
  1816. ControllerInformation - Array of pointers to the three pieces of
  1817. registry information.
  1818. PeripheralType - Should be a peripheral.
  1819. PeripheralNumber - Which peripheral - not used..
  1820. PeripheralInformation - Configuration information. Not Used.
  1821. Return Value:
  1822. STATUS_SUCCESS
  1823. --*/
  1824. {
  1825. PAGED_CODE();
  1826. *((BOOLEAN *)Context) = TRUE;
  1827. return STATUS_SUCCESS;
  1828. }
  1829. NTSTATUS
  1830. CyzControllerCallBack(
  1831. IN PVOID Context,
  1832. IN PUNICODE_STRING PathName,
  1833. IN INTERFACE_TYPE BusType,
  1834. IN ULONG BusNumber,
  1835. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  1836. IN CONFIGURATION_TYPE ControllerType,
  1837. IN ULONG ControllerNumber,
  1838. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  1839. IN CONFIGURATION_TYPE PeripheralType,
  1840. IN ULONG PeripheralNumber,
  1841. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  1842. )
  1843. /*++
  1844. Routine Description:
  1845. This routine is called to check if a particular item
  1846. is present in the registry.
  1847. Arguments:
  1848. Context - Pointer to a boolean.
  1849. PathName - unicode registry path. Not Used.
  1850. BusType - Internal, Isa, ...
  1851. BusNumber - Which bus if we are on a multibus system.
  1852. BusInformation - Configuration information about the bus. Not Used.
  1853. ControllerType - Controller type.
  1854. ControllerNumber - Which controller if there is more than one
  1855. controller in the system.
  1856. ControllerInformation - Array of pointers to the three pieces of
  1857. registry information.
  1858. PeripheralType - Should be a peripheral.
  1859. PeripheralNumber - Which peripheral - not used..
  1860. PeripheralInformation - Configuration information. Not Used.
  1861. Return Value:
  1862. STATUS_SUCCESS
  1863. --*/
  1864. {
  1865. PCM_FULL_RESOURCE_DESCRIPTOR controllerData;
  1866. PSERIAL_PTR_CTX pContext = (PSERIAL_PTR_CTX)Context;
  1867. ULONG i;
  1868. PAGED_CODE();
  1869. if (ControllerInformation[IoQueryDeviceConfigurationData]->DataLength == 0) {
  1870. pContext->isPointer = FALSE;
  1871. return STATUS_SUCCESS;
  1872. }
  1873. controllerData =
  1874. (PCM_FULL_RESOURCE_DESCRIPTOR)
  1875. (((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData])
  1876. + ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset);
  1877. //
  1878. // See if this is the exact port we are testing
  1879. //
  1880. for (i = 0; i < controllerData->PartialResourceList.Count; i++) {
  1881. PCM_PARTIAL_RESOURCE_DESCRIPTOR partial
  1882. = &controllerData->PartialResourceList.PartialDescriptors[i];
  1883. switch (partial->Type) {
  1884. case CmResourceTypePort:
  1885. if (partial->u.Port.Start.QuadPart == pContext->Port.QuadPart) {
  1886. //
  1887. // Pointer on same controller. Bail out.
  1888. //
  1889. pContext->isPointer = SERIAL_FOUNDPOINTER_PORT;
  1890. return STATUS_SUCCESS;
  1891. }
  1892. case CmResourceTypeInterrupt:
  1893. if (partial->u.Interrupt.Vector == pContext->Vector) {
  1894. //
  1895. // Pointer sharing this interrupt. Bail out.
  1896. //
  1897. pContext->isPointer = SERIAL_FOUNDPOINTER_VECTOR;
  1898. return STATUS_SUCCESS;
  1899. }
  1900. default:
  1901. break;
  1902. }
  1903. }
  1904. pContext->isPointer = FALSE;
  1905. return STATUS_SUCCESS;
  1906. }
  1907. NTSTATUS
  1908. CyzGetPortInfo(IN PDEVICE_OBJECT PDevObj, IN PCM_RESOURCE_LIST PResList,
  1909. IN PCM_RESOURCE_LIST PTrResList, OUT PCONFIG_DATA PConfig)
  1910. /*++
  1911. Routine Description:
  1912. This routine will get the configuration information and put
  1913. it and the translated values into CONFIG_DATA structures.
  1914. It first sets up with defaults and then queries the registry
  1915. to see if the user has overridden these defaults; if this is a legacy
  1916. multiport card, it uses the info in PUserData instead of groping the
  1917. registry again.
  1918. Arguments:
  1919. PDevObj - Pointer to the device object.
  1920. PResList - Pointer to the untranslated resources requested.
  1921. PTrResList - Pointer to the translated resources requested.
  1922. PConfig - Pointer to configuration info
  1923. Return Value:
  1924. STATUS_SUCCESS if consistant configuration was found - otherwise.
  1925. returns STATUS_SERIAL_NO_DEVICE_INITED.
  1926. --*/
  1927. {
  1928. PCYZ_DEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  1929. PDEVICE_OBJECT pLowerDevObj = pDevExt->LowerDeviceObject;
  1930. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  1931. CONFIGURATION_TYPE pointer = PointerPeripheral;
  1932. CONFIGURATION_TYPE controllerType = SerialController;
  1933. HANDLE keyHandle;
  1934. ULONG count;
  1935. ULONG i;
  1936. ULONG firmwareVersion;
  1937. INTERFACE_TYPE interfaceType;
  1938. PCM_PARTIAL_RESOURCE_LIST pPartialResourceList, pPartialTrResourceList;
  1939. PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialResourceDesc, pPartialTrResourceDesc;
  1940. PCM_FULL_RESOURCE_DESCRIPTOR pFullResourceDesc = NULL,
  1941. pFullTrResourceDesc = NULL;
  1942. // REMOVED BY FANNY
  1943. // ULONG defaultInterruptMode;
  1944. // ULONG defaultAddressSpace;
  1945. // ULONG defaultInterfaceType;
  1946. // ULONG defaultClockRate;
  1947. ULONG zero = 0;
  1948. // CYZ_PTR_CTX foundPointerCtx;
  1949. // ULONG isMulti = 0;
  1950. // ULONG gotInt = 0;
  1951. // ULONG gotISR = 0;
  1952. // ULONG gotIO = 0;
  1953. // ULONG ioResIndex = 0;
  1954. // ULONG curIoIndex = 0;
  1955. PAGED_CODE();
  1956. CyzDbgPrintEx(CYZTRACECALLS, "entering CyzGetPortInfo\n");
  1957. CyzDbgPrintEx(CYZPNPPOWER, "resource pointer is %x\n", PResList);
  1958. CyzDbgPrintEx(CYZPNPPOWER, "TR resource pointer is %x\n", PTrResList);
  1959. if ((PResList == NULL) || (PTrResList == NULL)) {
  1960. //
  1961. // This shouldn't happen in theory
  1962. //
  1963. ASSERT(PResList != NULL);
  1964. ASSERT(PTrResList != NULL);
  1965. //
  1966. // This status is as appropriate as I can think of
  1967. //
  1968. return STATUS_INSUFFICIENT_RESOURCES;
  1969. }
  1970. //
  1971. // Each resource list should have only one set of resources
  1972. //
  1973. ASSERT(PResList->Count == 1);
  1974. ASSERT(PTrResList->Count == 1);
  1975. //REMOVED BY FANNY
  1976. #if 0
  1977. //
  1978. // See if this is a multiport device. This way we allow other
  1979. // pseudo-serial devices with extra resources to specify another range
  1980. // of I/O ports. If this is not a multiport, we only look at the first
  1981. // range. If it is a multiport, we look at the first two ranges.
  1982. //
  1983. status = IoOpenDeviceRegistryKey(pDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  1984. STANDARD_RIGHTS_WRITE, &keyHandle);
  1985. if (!NT_SUCCESS(status)) {
  1986. return status;
  1987. }
  1988. status = CyzGetRegistryKeyValue(keyHandle, L"MultiportDevice",
  1989. sizeof(L"MultiportDevice"), &isMulti,
  1990. sizeof (ULONG));
  1991. if (!NT_SUCCESS(status)) {
  1992. isMulti = 0;
  1993. }
  1994. status = CyzGetRegistryKeyValue(keyHandle, L"CyzIoResourcesIndex",
  1995. sizeof(L"CyzIoResourcesIndex"),
  1996. &ioResIndex, sizeof(ULONG));
  1997. if (!NT_SUCCESS(status)) {
  1998. ioResIndex = 0;
  1999. }
  2000. ZwClose(keyHandle);
  2001. #endif // end removal code
  2002. pFullResourceDesc = &PResList->List[0];
  2003. pFullTrResourceDesc = &PTrResList->List[0];
  2004. //
  2005. // Ok, if we have a full resource descriptor. Let's take it apart.
  2006. //
  2007. if (pFullResourceDesc) {
  2008. pPartialResourceList = &pFullResourceDesc->PartialResourceList;
  2009. pPartialResourceDesc = pPartialResourceList->PartialDescriptors;
  2010. count = pPartialResourceList->Count;
  2011. //
  2012. // Pull out the stuff that is in the full descriptor.
  2013. //
  2014. PConfig->InterfaceType = pFullResourceDesc->InterfaceType;
  2015. PConfig->BusNumber = pFullResourceDesc->BusNumber;
  2016. //
  2017. // Now run through the partial resource descriptors looking for the Runtime memory,
  2018. // CD1400 memory, and interrupt.
  2019. //
  2020. for (i = 0; i < count; i++, pPartialResourceDesc++) {
  2021. switch (pPartialResourceDesc->Type) {
  2022. case CmResourceTypeMemory: {
  2023. if (pPartialResourceDesc->u.Memory.Length == CYZ_RUNTIME_LENGTH) {
  2024. PConfig->PhysicalRuntime = pPartialResourceDesc->u.Memory.Start;
  2025. PConfig->RuntimeLength = pPartialResourceDesc->u.Memory.Length;
  2026. PConfig->RuntimeAddressSpace = pPartialResourceDesc->Flags;
  2027. } else {
  2028. PConfig->PhysicalBoardMemory = pPartialResourceDesc->u.Memory.Start;
  2029. PConfig->BoardMemoryLength = pPartialResourceDesc->u.Memory.Length;
  2030. PConfig->BoardMemoryAddressSpace = pPartialResourceDesc->Flags;
  2031. }
  2032. break;
  2033. }
  2034. #ifndef POLL
  2035. case CmResourceTypeInterrupt: {
  2036. PConfig->OriginalIrql = pPartialResourceDesc->u.Interrupt.Level;
  2037. PConfig->OriginalVector =pPartialResourceDesc->u.Interrupt.Vector;
  2038. PConfig->Affinity = pPartialResourceDesc->u.Interrupt.Affinity;
  2039. if (pPartialResourceDesc->Flags
  2040. & CM_RESOURCE_INTERRUPT_LATCHED) {
  2041. PConfig->InterruptMode = Latched;
  2042. } else {
  2043. PConfig->InterruptMode = LevelSensitive;
  2044. }
  2045. break;
  2046. }
  2047. #endif
  2048. default: {
  2049. break;
  2050. }
  2051. } // switch (pPartialResourceDesc->Type)
  2052. } // for (i = 0; i < count; i++, pPartialResourceDesc++)
  2053. } // if (pFullResourceDesc)
  2054. //
  2055. // Do the same for the translated resources
  2056. //
  2057. if (pFullTrResourceDesc) {
  2058. pPartialTrResourceList = &pFullTrResourceDesc->PartialResourceList;
  2059. pPartialTrResourceDesc = pPartialTrResourceList->PartialDescriptors;
  2060. count = pPartialTrResourceList->Count;
  2061. //
  2062. // Reload PConfig with the translated values for later use
  2063. //
  2064. PConfig->InterfaceType = pFullTrResourceDesc->InterfaceType;
  2065. PConfig->BusNumber = pFullTrResourceDesc->BusNumber;
  2066. for (i = 0; i < count; i++, pPartialTrResourceDesc++) {
  2067. switch (pPartialTrResourceDesc->Type) {
  2068. case CmResourceTypeMemory: {
  2069. // ATTENTION, ATTENTION: FOR NOW, WE WILL USE THE RAW
  2070. // RESOURCES, AS WE HAVE GARBAGE IN THE TRANSLATED
  2071. // RESOURCES.
  2072. //
  2073. if (pPartialTrResourceDesc->u.Memory.Length == CYZ_RUNTIME_LENGTH) {
  2074. PConfig->TranslatedRuntime = pPartialTrResourceDesc->u.Memory.Start;
  2075. PConfig->RuntimeLength = pPartialTrResourceDesc->u.Memory.Length;
  2076. } else {
  2077. PConfig->TranslatedBoardMemory = pPartialTrResourceDesc->u.Memory.Start;
  2078. PConfig->BoardMemoryLength = pPartialTrResourceDesc->u.Memory.Length;
  2079. }
  2080. //TEMP CODE BECAUSE OUR BUS DRIVER IS GIVING WRONG TRANSLATED ADDRESS
  2081. //PConfig->TranslatedRuntime = PConfig->PhysicalRuntime;
  2082. //PConfig->TranslatedBoardMemory = PConfig->PhysicalBoardMemory;
  2083. break;
  2084. }
  2085. #ifndef POLL
  2086. case CmResourceTypeInterrupt: {
  2087. PConfig->TrVector = pPartialTrResourceDesc->u.Interrupt.Vector;
  2088. PConfig->TrIrql = pPartialTrResourceDesc->u.Interrupt.Level;
  2089. PConfig->Affinity = pPartialTrResourceDesc->u.Interrupt.Affinity;
  2090. break;
  2091. }
  2092. #endif
  2093. default: {
  2094. break;
  2095. }
  2096. } // switch (pPartialTrResourceDesc->Type)
  2097. } // for (i = 0; i < count; i++, pPartialTrResourceDesc++)
  2098. } // if (pFullTrResourceDesc)
  2099. //
  2100. // Initialize a config data structure with default values for those that
  2101. // may not already be initialized.
  2102. //
  2103. PConfig->PortIndex = 0;
  2104. firmwareVersion = 0;
  2105. // PConfig->RxFIFO = driverDefaults.RxFIFODefault;
  2106. // PConfig->TxFIFO = driverDefaults.TxFIFODefault;
  2107. //
  2108. // Open the "Device Parameters" section of registry for this device object.
  2109. //
  2110. status = IoOpenDeviceRegistryKey (pDevExt->Pdo,
  2111. PLUGPLAY_REGKEY_DEVICE,
  2112. STANDARD_RIGHTS_READ,
  2113. &keyHandle);
  2114. if (!NT_SUCCESS(status)) {
  2115. CyzDbgPrintEx(CYZERRORS, "IoOpenDeviceRegistryKey failed - %x \n",
  2116. status);
  2117. goto PortInfoCleanUp;
  2118. } else {
  2119. // status = CyzGetRegistryKeyValue (keyHandle,
  2120. // L"RxFIFO",
  2121. // sizeof(L"RxFIFO"),
  2122. // &PConfig->RxFIFO,
  2123. // sizeof (ULONG));
  2124. // status = CyzGetRegistryKeyValue (keyHandle,
  2125. // L"TxFIFO",
  2126. // sizeof(L"TxFIFO"),
  2127. // &PConfig->TxFIFO,
  2128. // sizeof (ULONG));
  2129. status = CyzGetRegistryKeyValue (keyHandle,
  2130. L"PortIndex",
  2131. sizeof(L"PortIndex"),
  2132. &PConfig->PortIndex,
  2133. sizeof (ULONG));
  2134. if (!NT_SUCCESS(status)) {
  2135. PConfig->PortIndex = MAXULONG; // just some invalid number (fanny)
  2136. }
  2137. status = CyzGetRegistryKeyValue(keyHandle,
  2138. L"FirmwareVersion",
  2139. sizeof(L"FirmwareVersion"),
  2140. &firmwareVersion,
  2141. sizeof(ULONG));
  2142. if (!NT_SUCCESS(status)) {
  2143. firmwareVersion = 0;
  2144. CyzDbgPrintEx(CYZERRORS, "CyzGetRegistryKeyValue FirmwareVersion "
  2145. "failed - %x\n", status);
  2146. }
  2147. // status = CyzGetRegistryKeyValue (keyHandle,
  2148. // L"PPPaware",
  2149. // sizeof(L"PPPaware"),
  2150. // &PConfig->PPPaware,
  2151. // sizeof (ULONG));
  2152. // if (!NT_SUCCESS(status)) {
  2153. // PConfig->PPPaware = FALSE; // That's the default mode.
  2154. // }
  2155. status = CyzGetRegistryKeyValue (keyHandle,
  2156. L"WriteComplete",
  2157. sizeof(L"WriteComplete"),
  2158. &PConfig->WriteComplete,
  2159. sizeof (ULONG));
  2160. if (!NT_SUCCESS(status)) {
  2161. PConfig->WriteComplete = FALSE; // That's the default mode.
  2162. }
  2163. ZwClose (keyHandle);
  2164. }
  2165. //
  2166. // Do some error checking on the configuration info we have.
  2167. //
  2168. // Make sure that the interrupt is non zero (which we defaulted
  2169. // it to).
  2170. //
  2171. // Make sure that the portaddress is non zero (which we defaulted
  2172. // it to).
  2173. //
  2174. // Make sure that the DosDevices is not NULL (which we defaulted
  2175. // it to).
  2176. //
  2177. // We need to make sure that if an interrupt status
  2178. // was specified, that a port index was also specfied,
  2179. // and if so that the port index is <= maximum ports
  2180. // on a board.
  2181. //
  2182. // We should also validate that the bus type and number
  2183. // are correct.
  2184. //
  2185. // We will also validate that the interrupt mode makes
  2186. // sense for the bus.
  2187. //
  2188. //*****************************************
  2189. // Error Injection
  2190. // PConfig->PhysicalRuntime.LowPart = NULL;
  2191. // PConfig->PhysicalBoardMemory.LowPart = NULL;
  2192. // PConfig->OriginalVector = NULL;
  2193. // PConfig->PortIndex = MAXULONG;
  2194. //*****************************************
  2195. if (!PConfig->PhysicalRuntime.LowPart) {
  2196. //
  2197. // Ehhhh! Lose Game.
  2198. //
  2199. CyzLogError(
  2200. PDevObj->DriverObject,
  2201. NULL,
  2202. PConfig->PhysicalBoardMemory,
  2203. CyzPhysicalZero,
  2204. 0,
  2205. 0,
  2206. 0,
  2207. PConfig->PortIndex+1,
  2208. STATUS_SUCCESS,
  2209. CYZ_INVALID_RUNTIME_REGISTERS,
  2210. pDevExt->DeviceName.Length,
  2211. pDevExt->DeviceName.Buffer,
  2212. 0,
  2213. NULL
  2214. );
  2215. CyzDbgPrintEx(CYZERRORS,"Bogus Runtime address %x\n",
  2216. PConfig->PhysicalRuntime.LowPart);
  2217. //status = CYZ_INVALID_RUNTIME_REGISTERS;
  2218. status = STATUS_INSUFFICIENT_RESOURCES;
  2219. goto PortInfoCleanUp;
  2220. }
  2221. if (!PConfig->PhysicalBoardMemory.LowPart) {
  2222. //
  2223. // Ehhhh! Lose Game.
  2224. //
  2225. CyzLogError(
  2226. PDevObj->DriverObject,
  2227. NULL,
  2228. PConfig->PhysicalBoardMemory,
  2229. CyzPhysicalZero,
  2230. 0,
  2231. 0,
  2232. 0,
  2233. PConfig->PortIndex+1,
  2234. STATUS_SUCCESS,
  2235. CYZ_INVALID_BOARD_MEMORY,
  2236. pDevExt->DeviceName.Length,
  2237. pDevExt->DeviceName.Buffer,
  2238. 0,
  2239. NULL
  2240. );
  2241. CyzDbgPrintEx(CYZERRORS,"Bogus board address %x\n",
  2242. PConfig->PhysicalBoardMemory.LowPart);
  2243. //status = CYZ_INVALID_BOARD_MEMORY;
  2244. status = STATUS_INSUFFICIENT_RESOURCES;
  2245. goto PortInfoCleanUp;
  2246. }
  2247. #ifndef POLL
  2248. if (!PConfig->OriginalVector) {
  2249. //
  2250. // Ehhhh! Lose Game.
  2251. //
  2252. CyzLogError(
  2253. pDevExt->DriverObject,
  2254. NULL,
  2255. PConfig->PhysicalBoardMemory,
  2256. CyzPhysicalZero,
  2257. 0,
  2258. 0,
  2259. 0,
  2260. PConfig->PortIndex+1,
  2261. STATUS_SUCCESS,
  2262. CYZ_INVALID_INTERRUPT,
  2263. pDevExt->DeviceName.Length,
  2264. pDevExt->DeviceName.Buffer,
  2265. 0,
  2266. NULL
  2267. );
  2268. CyzDbgPrintEx(CYZERRORS, "Bogus vector %x\n", PConfig->OriginalVector);
  2269. //status = CYZ_INVALID_INTERRUPT;
  2270. status = STATUS_INSUFFICIENT_RESOURCES;
  2271. goto PortInfoCleanUp;
  2272. }
  2273. #endif
  2274. if (firmwareVersion < Z_COMPATIBLE_FIRMWARE) {
  2275. UNICODE_STRING FwVersion;
  2276. WCHAR FwVersionBuffer[10];
  2277. RtlInitUnicodeString(&FwVersion, NULL);
  2278. FwVersion.MaximumLength = sizeof(FwVersionBuffer);
  2279. FwVersion.Buffer = FwVersionBuffer;
  2280. RtlIntegerToUnicodeString(Z_COMPATIBLE_FIRMWARE, 16, &FwVersion);
  2281. CyzDbgPrintEx(CYZERRORS,"Incompatible firmware\n");
  2282. CyzLogError( pDevExt->DriverObject,NULL,
  2283. PConfig->PhysicalBoardMemory,CyzPhysicalZero,
  2284. 0,0,0,0,status,CYZ_INCOMPATIBLE_FIRMWARE,
  2285. FwVersion.Length,FwVersion.Buffer,0,NULL);
  2286. status = STATUS_SERIAL_NO_DEVICE_INITED;
  2287. goto PortInfoCleanUp;
  2288. }
  2289. if (PConfig->PortIndex >= CYZ_MAX_PORTS) {
  2290. CyzLogError(
  2291. pDevExt->DriverObject,
  2292. NULL,
  2293. PConfig->PhysicalBoardMemory,
  2294. CyzPhysicalZero,
  2295. 0,
  2296. 0,
  2297. 0,
  2298. PConfig->PortIndex,
  2299. STATUS_SUCCESS,
  2300. CYZ_PORT_INDEX_TOO_HIGH,
  2301. pDevExt->DeviceName.Length,
  2302. pDevExt->DeviceName.Buffer,
  2303. 0,
  2304. NULL
  2305. );
  2306. CyzDbgPrintEx (CYZERRORS,"Port index too large %x\n",PConfig->PortIndex);
  2307. //status = CYZ_PORT_INDEX_TOO_HIGH;
  2308. status = STATUS_INSUFFICIENT_RESOURCES;
  2309. goto PortInfoCleanUp;
  2310. }
  2311. //
  2312. // We don't want to cause the hal to have a bad day,
  2313. // so let's check the interface type and bus number.
  2314. //
  2315. // We only need to check the registry if they aren't
  2316. // equal to the defaults.
  2317. //
  2318. if (PConfig->BusNumber != 0) {
  2319. BOOLEAN foundIt;
  2320. //**************************************************
  2321. // Error Injection
  2322. // PConfig->InterfaceType = MaximumInterfaceType;
  2323. //**************************************************
  2324. if (PConfig->InterfaceType >= MaximumInterfaceType) {
  2325. //
  2326. // Ehhhh! Lose Game.
  2327. //
  2328. CyzLogError(
  2329. pDevExt->DriverObject,
  2330. NULL,
  2331. PConfig->PhysicalBoardMemory,
  2332. CyzPhysicalZero,
  2333. 0,
  2334. 0,
  2335. 0,
  2336. PConfig->PortIndex+1,
  2337. STATUS_SUCCESS,
  2338. CYZ_UNKNOWN_BUS,
  2339. pDevExt->DeviceName.Length,
  2340. pDevExt->DeviceName.Buffer,
  2341. 0,
  2342. NULL
  2343. );
  2344. CyzDbgPrintEx(CYZERRORS, "Invalid Bus type %x\n",
  2345. PConfig->BusNumber);
  2346. //status = CYZ_UNKNOWN_BUS;
  2347. status = STATUS_INSUFFICIENT_RESOURCES;
  2348. goto PortInfoCleanUp;
  2349. }
  2350. IoQueryDeviceDescription(
  2351. (INTERFACE_TYPE *)&PConfig->InterfaceType,
  2352. &zero,
  2353. NULL,
  2354. NULL,
  2355. NULL,
  2356. NULL,
  2357. CyzItemCallBack,
  2358. &foundIt
  2359. );
  2360. //**************************************************
  2361. // Error Injection
  2362. // foundIt = FALSE;
  2363. //**************************************************
  2364. if (!foundIt) {
  2365. CyzLogError(
  2366. pDevExt->DriverObject,
  2367. NULL,
  2368. PConfig->PhysicalBoardMemory,
  2369. CyzPhysicalZero,
  2370. 0,
  2371. 0,
  2372. 0,
  2373. PConfig->PortIndex+1,
  2374. STATUS_SUCCESS,
  2375. CYZ_BUS_NOT_PRESENT,
  2376. pDevExt->DeviceName.Length,
  2377. pDevExt->DeviceName.Buffer,
  2378. 0,
  2379. NULL
  2380. );
  2381. CyzDbgPrintEx(CYZERRORS, "There aren't that many of those\n"
  2382. "busses on this system,%x\n", PConfig->BusNumber);
  2383. //status = CYZ_BUS_NOT_PRESENT;
  2384. status = STATUS_INSUFFICIENT_RESOURCES;
  2385. goto PortInfoCleanUp;
  2386. }
  2387. } // if (PConfig->BusNumber != 0)
  2388. status = STATUS_SUCCESS;
  2389. //
  2390. // Dump out the port configuration.
  2391. //
  2392. CyzDbgPrintEx(CYZDIAG1, "Runtime Memory address: %x\n",
  2393. PConfig->PhysicalRuntime.LowPart);
  2394. CyzDbgPrintEx(CYZDIAG1, "Board Memory address: %x\n",
  2395. PConfig->PhysicalBoardMemory.LowPart);
  2396. CyzDbgPrintEx(CYZDIAG1, "Com Port Index: %x\n",
  2397. PConfig->PortIndex);
  2398. CyzDbgPrintEx(CYZDIAG1, "Com Port BusNumber: %x\n",
  2399. PConfig->BusNumber);
  2400. CyzDbgPrintEx(CYZDIAG1, "Com Runtime AddressSpace: %x\n",
  2401. PConfig->RuntimeAddressSpace);
  2402. CyzDbgPrintEx(CYZDIAG1, "Com Board AddressSpace: %x\n",
  2403. PConfig->BoardMemoryAddressSpace);
  2404. CyzDbgPrintEx(CYZDIAG1, "Com InterfaceType: %x\n",
  2405. PConfig->InterfaceType);
  2406. #ifndef POLL
  2407. CyzDbgPrintEx(CYZDIAG1, "Com InterruptMode: %x\n",
  2408. PConfig->InterruptMode);
  2409. CyzDbgPrintEx(CYZDIAG1, "Com OriginalVector: %x\n",
  2410. PConfig->OriginalVector);
  2411. CyzDbgPrintEx(CYZDIAG1, "Com OriginalIrql: %x\n",
  2412. PConfig->OriginalIrql);
  2413. #endif
  2414. PortInfoCleanUp:;
  2415. return status;
  2416. }
  2417. NTSTATUS
  2418. CyzReadSymName(IN PCYZ_DEVICE_EXTENSION PDevExt, IN HANDLE hRegKey,
  2419. OUT PUNICODE_STRING PSymName, OUT PWCHAR *PpRegName)
  2420. {
  2421. NTSTATUS status;
  2422. UNICODE_STRING linkName;
  2423. PDRIVER_OBJECT pDrvObj;
  2424. PDEVICE_OBJECT pDevObj;
  2425. pDevObj = PDevExt->DeviceObject;
  2426. pDrvObj = pDevObj->DriverObject;
  2427. *PpRegName = NULL;
  2428. RtlZeroMemory(&linkName, sizeof(UNICODE_STRING));
  2429. linkName.MaximumLength = SYMBOLIC_NAME_LENGTH*sizeof(WCHAR);
  2430. linkName.Buffer = ExAllocatePool(PagedPool | POOL_COLD_ALLOCATION, linkName.MaximumLength
  2431. + sizeof(WCHAR));
  2432. if (linkName.Buffer == NULL) {
  2433. CyzLogError(pDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2434. 0, 0, 0, 19, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  2435. 0, NULL, 0, NULL);
  2436. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for device name\n");
  2437. status = STATUS_INSUFFICIENT_RESOURCES;
  2438. goto CyzReadSymNameError;
  2439. }
  2440. RtlZeroMemory(linkName.Buffer, linkName.MaximumLength + sizeof(WCHAR));
  2441. *PpRegName = ExAllocatePool(PagedPool | POOL_COLD_ALLOCATION, SYMBOLIC_NAME_LENGTH * sizeof(WCHAR)
  2442. + sizeof(WCHAR));
  2443. if (*PpRegName == NULL) {
  2444. CyzLogError(pDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2445. 0, 0, 0, 19, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  2446. 0, NULL, 0, NULL);
  2447. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for buffer\n");
  2448. status = STATUS_INSUFFICIENT_RESOURCES;
  2449. goto CyzReadSymNameError;
  2450. }
  2451. //
  2452. // Fetch PortName which contains the suggested REG_SZ symbolic name.
  2453. //
  2454. status = CyzGetRegistryKeyValue(hRegKey, L"PortName",
  2455. sizeof(L"PortName"), *PpRegName,
  2456. SYMBOLIC_NAME_LENGTH * sizeof(WCHAR));
  2457. if (!NT_SUCCESS(status)) {
  2458. //
  2459. // This is for PCMCIA which currently puts the name under Identifier.
  2460. //
  2461. status = CyzGetRegistryKeyValue(hRegKey, L"Identifier",
  2462. sizeof(L"Identifier"),
  2463. *PpRegName, SYMBOLIC_NAME_LENGTH
  2464. * sizeof(WCHAR));
  2465. if (!NT_SUCCESS(status)) {
  2466. //
  2467. // Hmm. Either we have to pick a name or bail...
  2468. //
  2469. // ...we will bail.
  2470. //
  2471. CyzDbgPrintEx(CYZERRORS, "Getting PortName/Identifier failed - "
  2472. "%x\n", status);
  2473. goto CyzReadSymNameError;
  2474. }
  2475. }
  2476. //
  2477. // Create the "\\DosDevices\\<symbolicName>" string
  2478. //
  2479. RtlAppendUnicodeToString(&linkName, L"\\");
  2480. RtlAppendUnicodeToString(&linkName, DEFAULT_DIRECTORY);
  2481. RtlAppendUnicodeToString(&linkName, L"\\");
  2482. RtlAppendUnicodeToString(&linkName, *PpRegName);
  2483. PSymName->MaximumLength = linkName.Length + sizeof(WCHAR);
  2484. PSymName->Buffer = ExAllocatePool(PagedPool | POOL_COLD_ALLOCATION, PSymName->MaximumLength);
  2485. if (PSymName->Buffer == NULL) {
  2486. status = STATUS_INSUFFICIENT_RESOURCES;
  2487. goto CyzReadSymNameError;
  2488. }
  2489. RtlZeroMemory(PSymName->Buffer, PSymName->MaximumLength);
  2490. RtlAppendUnicodeStringToString(PSymName, &linkName);
  2491. CyzDbgPrintEx(CYZDIAG1, "Read name %wZ\n", PSymName);
  2492. CyzReadSymNameError:
  2493. if (linkName.Buffer != NULL) {
  2494. ExFreePool(linkName.Buffer);
  2495. linkName.Buffer = NULL;
  2496. }
  2497. if (!NT_SUCCESS(status)) {
  2498. if (*PpRegName != NULL) {
  2499. ExFreePool(*PpRegName);
  2500. *PpRegName = NULL;
  2501. }
  2502. }
  2503. return status;
  2504. }
  2505. NTSTATUS
  2506. CyzDoExternalNaming(IN PCYZ_DEVICE_EXTENSION PDevExt,
  2507. IN PDRIVER_OBJECT PDrvObj)
  2508. /*++
  2509. Routine Description:
  2510. This routine will be used to create a symbolic link
  2511. to the driver name in the given object directory.
  2512. It will also create an entry in the device map for
  2513. this device - IF we could create the symbolic link.
  2514. Arguments:
  2515. Extension - Pointer to the device extension.
  2516. Return Value:
  2517. None.
  2518. --*/
  2519. {
  2520. NTSTATUS status = STATUS_SUCCESS;
  2521. HANDLE keyHandle;
  2522. WCHAR *pRegName = NULL;
  2523. UNICODE_STRING linkName;
  2524. PDEVICE_OBJECT pLowerDevObj, pDevObj;
  2525. ULONG bufLen;
  2526. PAGED_CODE();
  2527. pDevObj = PDevExt->DeviceObject;
  2528. pLowerDevObj = PDevExt->LowerDeviceObject;
  2529. status = IoOpenDeviceRegistryKey(PDevExt->Pdo, PLUGPLAY_REGKEY_DEVICE,
  2530. STANDARD_RIGHTS_READ, &keyHandle);
  2531. //
  2532. // Check to see if we are allowed to do external naming; if not,
  2533. // then we just return success
  2534. //
  2535. if (status != STATUS_SUCCESS) {
  2536. return status;
  2537. }
  2538. CyzGetRegistryKeyValue(keyHandle, L"CyzSkipExternalNaming",
  2539. sizeof(L"CyzSkipExternalNaming"),
  2540. &PDevExt->SkipNaming, sizeof(ULONG));
  2541. if (PDevExt->SkipNaming) {
  2542. ZwClose(keyHandle);
  2543. return STATUS_SUCCESS;
  2544. }
  2545. RtlZeroMemory(&linkName, sizeof(UNICODE_STRING));
  2546. linkName.MaximumLength = SYMBOLIC_NAME_LENGTH*sizeof(WCHAR);
  2547. linkName.Buffer = ExAllocatePool(PagedPool, linkName.MaximumLength
  2548. + sizeof(WCHAR)); //TODO:"| POOL_COLD_ALLOCATION"???
  2549. //************************************
  2550. //Error Injection
  2551. //
  2552. //if (linkName.Buffer != NULL) {
  2553. // ExFreePool(linkName.Buffer);
  2554. //}
  2555. //linkName.Buffer = NULL;
  2556. //************************************
  2557. if (linkName.Buffer == NULL) {
  2558. CyzLogError(PDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2559. 0, 0, 0, 71, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  2560. 0, NULL, 0, NULL);
  2561. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for device name\n");
  2562. status = STATUS_INSUFFICIENT_RESOURCES;
  2563. ZwClose(keyHandle);
  2564. goto CyzDoExternalNamingError;
  2565. }
  2566. RtlZeroMemory(linkName.Buffer, linkName.MaximumLength + sizeof(WCHAR));
  2567. pRegName = ExAllocatePool(PagedPool, SYMBOLIC_NAME_LENGTH * sizeof(WCHAR)
  2568. + sizeof(WCHAR)); //TODO:"| POOL_COLD_ALLOCATION"???
  2569. //************************************
  2570. //Error Injection
  2571. //
  2572. //if (pRegName != NULL) {
  2573. // ExFreePool(pRegName);
  2574. //}
  2575. //pRegName = NULL;
  2576. //************************************
  2577. if (pRegName == NULL) {
  2578. CyzLogError(PDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2579. 0, 0, 0, 72, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  2580. 0, NULL, 0, NULL);
  2581. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for buffer\n");
  2582. status = STATUS_INSUFFICIENT_RESOURCES;
  2583. ZwClose(keyHandle);
  2584. goto CyzDoExternalNamingError;
  2585. }
  2586. //
  2587. // Fetch PortName which contains the suggested REG_SZ symbolic name.
  2588. //
  2589. status = CyzGetRegistryKeyValue(keyHandle, L"PortName",
  2590. sizeof(L"PortName"), pRegName,
  2591. SYMBOLIC_NAME_LENGTH * sizeof(WCHAR));
  2592. if (!NT_SUCCESS(status)) {
  2593. //
  2594. // This is for PCMCIA which currently puts the name under Identifier.
  2595. //
  2596. status = CyzGetRegistryKeyValue(keyHandle, L"Identifier",
  2597. sizeof(L"Identifier"),
  2598. pRegName, SYMBOLIC_NAME_LENGTH
  2599. * sizeof(WCHAR));
  2600. if (!NT_SUCCESS(status)) {
  2601. //
  2602. // Hmm. Either we have to pick a name or bail...
  2603. //
  2604. // ...we will bail.
  2605. //
  2606. CyzDbgPrintEx(CYZERRORS, "Getting PortName/Identifier failed - "
  2607. "%x\n", status);
  2608. ZwClose (keyHandle);
  2609. goto CyzDoExternalNamingError;
  2610. }
  2611. }
  2612. ZwClose (keyHandle);
  2613. bufLen = wcslen(pRegName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
  2614. PDevExt->WmiIdentifier.Buffer = ExAllocatePool(PagedPool, bufLen);
  2615. //************************************
  2616. //Error Injection
  2617. //
  2618. //if (PDevExt->WmiIdentifier.Buffer != NULL) {
  2619. // ExFreePool(PDevExt->WmiIdentifier.Buffer);
  2620. //}
  2621. //PDevExt->WmiIdentifier.Buffer = NULL;
  2622. //************************************
  2623. if (PDevExt->WmiIdentifier.Buffer == NULL) {
  2624. CyzLogError(PDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2625. 0, 0, 0, 73, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  2626. 0, NULL, 0, NULL);
  2627. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for WMI name\n");
  2628. status = STATUS_INSUFFICIENT_RESOURCES;
  2629. goto CyzDoExternalNamingError;
  2630. }
  2631. RtlZeroMemory(PDevExt->WmiIdentifier.Buffer, bufLen);
  2632. PDevExt->WmiIdentifier.Length = 0;
  2633. PDevExt->WmiIdentifier.MaximumLength = (USHORT)bufLen - 1;
  2634. RtlAppendUnicodeToString(&PDevExt->WmiIdentifier, pRegName);
  2635. //
  2636. // Create the "\\DosDevices\\<symbolicName>" string
  2637. //
  2638. RtlAppendUnicodeToString(&linkName, L"\\");
  2639. RtlAppendUnicodeToString(&linkName, DEFAULT_DIRECTORY);
  2640. RtlAppendUnicodeToString(&linkName, L"\\");
  2641. RtlAppendUnicodeToString(&linkName, pRegName);
  2642. //
  2643. // Allocate Pool and save the symbolic link name in the device extension.
  2644. //
  2645. PDevExt->SymbolicLinkName.MaximumLength = linkName.Length + sizeof(WCHAR);
  2646. PDevExt->SymbolicLinkName.Buffer
  2647. = ExAllocatePool(PagedPool, PDevExt->SymbolicLinkName.MaximumLength);
  2648. //TODO:"| POOL_COLD_ALLOCATION"???
  2649. if (!PDevExt->SymbolicLinkName.Buffer) {
  2650. CyzLogError(PDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2651. 0, 0, 0, 74, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  2652. 0, NULL, 0, NULL);
  2653. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for symbolic link "
  2654. "name\n");
  2655. status = STATUS_INSUFFICIENT_RESOURCES;
  2656. goto CyzDoExternalNamingError;
  2657. }
  2658. //
  2659. // Zero fill it.
  2660. //
  2661. RtlZeroMemory(PDevExt->SymbolicLinkName.Buffer,
  2662. PDevExt->SymbolicLinkName.MaximumLength);
  2663. RtlAppendUnicodeStringToString(&PDevExt->SymbolicLinkName,
  2664. &linkName);
  2665. PDevExt->DosName.Buffer = ExAllocatePool(PagedPool, 64 + sizeof(WCHAR));
  2666. if (!PDevExt->DosName.Buffer) {
  2667. CyzLogError(PDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2668. 0, 0, 0, 75, STATUS_SUCCESS, CYZ_INSUFFICIENT_RESOURCES,
  2669. 0, NULL, 0, NULL);
  2670. CyzDbgPrintEx(CYZERRORS, "Couldn't allocate memory for Dos name\n");
  2671. status = STATUS_INSUFFICIENT_RESOURCES;
  2672. goto CyzDoExternalNamingError;
  2673. }
  2674. PDevExt->DosName.MaximumLength = 64 + sizeof(WCHAR);
  2675. //
  2676. // Zero fill it.
  2677. //
  2678. PDevExt->DosName.Length = 0;
  2679. RtlZeroMemory(PDevExt->DosName.Buffer,
  2680. PDevExt->DosName.MaximumLength);
  2681. RtlAppendUnicodeToString(&PDevExt->DosName, pRegName);
  2682. RtlZeroMemory(((PUCHAR)(&PDevExt->DosName.Buffer[0]))
  2683. + PDevExt->DosName.Length, sizeof(WCHAR));
  2684. CyzDbgPrintEx(CYZDIAG1, "DosName is %wZ\n", &PDevExt->DosName);
  2685. status = IoCreateSymbolicLink (&PDevExt->SymbolicLinkName,
  2686. &PDevExt->DeviceName);
  2687. //************************************
  2688. //Error Injection
  2689. //IoDeleteSymbolicLink(&PDevExt->SymbolicLinkName);
  2690. //status = STATUS_INVALID_PARAMETER;
  2691. //************************************
  2692. if (!NT_SUCCESS(status)) {
  2693. //
  2694. // Oh well, couldn't create the symbolic link. No point
  2695. // in trying to create the device map entry.
  2696. //
  2697. CyzLogError(PDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2698. 0, 0, 0, PDevExt->PortIndex+1, status, CYZ_NO_SYMLINK_CREATED,
  2699. PDevExt->DeviceName.Length + sizeof(WCHAR),
  2700. PDevExt->DeviceName.Buffer, 0, NULL);
  2701. CyzDbgPrintEx(CYZERRORS, "Couldn't create the symbolic link\n"
  2702. "for port %wZ\n", &PDevExt->DeviceName);
  2703. goto CyzDoExternalNamingError;
  2704. }
  2705. PDevExt->CreatedSymbolicLink = TRUE;
  2706. status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"SERIALCOMM",
  2707. PDevExt->DeviceName.Buffer, REG_SZ,
  2708. PDevExt->DosName.Buffer,
  2709. PDevExt->DosName.Length + sizeof(WCHAR));
  2710. //************************************
  2711. //Error Injection
  2712. //RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  2713. // PDevExt->DeviceName.Buffer);
  2714. //status = STATUS_INVALID_PARAMETER;
  2715. //************************************
  2716. if (!NT_SUCCESS(status)) {
  2717. CyzLogError(PDrvObj, pDevObj, CyzPhysicalZero, CyzPhysicalZero,
  2718. 0, 0, 0, PDevExt->PortIndex+1, status, CYZ_NO_DEVICE_MAP_CREATED,
  2719. PDevExt->DeviceName.Length + sizeof(WCHAR),
  2720. PDevExt->DeviceName.Buffer, 0, NULL);
  2721. CyzDbgPrintEx(CYZERRORS, "Couldn't create the device map entry\n"
  2722. "------- for port %wZ\n", &PDevExt->DeviceName);
  2723. goto CyzDoExternalNamingError;
  2724. }
  2725. PDevExt->CreatedSerialCommEntry = TRUE;
  2726. //
  2727. // Make the device visible via a device association as well.
  2728. // The reference string is the eight digit device index
  2729. //
  2730. status = IoRegisterDeviceInterface(PDevExt->Pdo, (LPGUID)&GUID_CLASS_COMPORT,
  2731. NULL, &PDevExt->DeviceClassSymbolicName);
  2732. if (!NT_SUCCESS(status)) {
  2733. CyzDbgPrintEx(CYZERRORS, "Couldn't register class association\n"
  2734. "for port %wZ\n", &PDevExt->DeviceName);
  2735. PDevExt->DeviceClassSymbolicName.Buffer = NULL;
  2736. goto CyzDoExternalNamingError;
  2737. }
  2738. //
  2739. // Now set the symbolic link for the association
  2740. //
  2741. status = IoSetDeviceInterfaceState(&PDevExt->DeviceClassSymbolicName,
  2742. TRUE);
  2743. if (!NT_SUCCESS(status)) {
  2744. CyzDbgPrintEx(CYZERRORS, "Couldn't set class association"
  2745. " for port %wZ\n", &PDevExt->DeviceName);
  2746. }
  2747. CyzDoExternalNamingError:;
  2748. //
  2749. // Clean up error conditions
  2750. //
  2751. if (!NT_SUCCESS(status)) {
  2752. if (PDevExt->DosName.Buffer != NULL) {
  2753. ExFreePool(PDevExt->DosName.Buffer);
  2754. PDevExt->DosName.Buffer = NULL;
  2755. }
  2756. if (PDevExt->CreatedSymbolicLink == TRUE) {
  2757. IoDeleteSymbolicLink(&PDevExt->SymbolicLinkName);
  2758. PDevExt->CreatedSymbolicLink = FALSE;
  2759. }
  2760. if (PDevExt->SymbolicLinkName.Buffer != NULL) {
  2761. ExFreePool(PDevExt->SymbolicLinkName.Buffer);
  2762. PDevExt->SymbolicLinkName.Buffer = NULL;
  2763. }
  2764. if (PDevExt->DeviceName.Buffer != NULL) {
  2765. RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  2766. PDevExt->DeviceName.Buffer);
  2767. }
  2768. if (PDevExt->DeviceClassSymbolicName.Buffer) {
  2769. IoSetDeviceInterfaceState(&PDevExt->DeviceClassSymbolicName, FALSE);
  2770. ExFreePool(PDevExt->DeviceClassSymbolicName.Buffer); //Added in DDK 2269
  2771. PDevExt->DeviceClassSymbolicName.Buffer = NULL; //Added in DDK 2269
  2772. }
  2773. if (PDevExt->WmiIdentifier.Buffer != NULL) {
  2774. ExFreePool(PDevExt->WmiIdentifier.Buffer);
  2775. PDevExt->WmiIdentifier.Buffer = NULL;
  2776. }
  2777. }
  2778. //
  2779. // Always clean up our temp buffers.
  2780. //
  2781. if (linkName.Buffer != NULL) {
  2782. ExFreePool(linkName.Buffer);
  2783. }
  2784. if (pRegName != NULL) {
  2785. ExFreePool(pRegName);
  2786. }
  2787. return status;
  2788. }
  2789. VOID
  2790. CyzUndoExternalNaming(IN PCYZ_DEVICE_EXTENSION Extension)
  2791. /*++
  2792. Routine Description:
  2793. This routine will be used to delete a symbolic link
  2794. to the driver name in the given object directory.
  2795. It will also delete an entry in the device map for
  2796. this device if the symbolic link had been created.
  2797. Arguments:
  2798. Extension - Pointer to the device extension.
  2799. Return Value:
  2800. None.
  2801. --*/
  2802. {
  2803. NTSTATUS status;
  2804. HANDLE keyHandle;
  2805. PAGED_CODE();
  2806. CyzDbgPrintEx(CYZDIAG3, "In CyzUndoExternalNaming for "
  2807. "extension: %x of port %wZ\n",
  2808. Extension,&Extension->DeviceName);
  2809. //
  2810. // Maybe there is nothing for us to do
  2811. //
  2812. if (Extension->SkipNaming) {
  2813. return;
  2814. }
  2815. //
  2816. // We're cleaning up here. One reason we're cleaning up
  2817. // is that we couldn't allocate space for the directory
  2818. // name or the symbolic link.
  2819. //
  2820. if (Extension->SymbolicLinkName.Buffer && Extension->CreatedSymbolicLink) {
  2821. if (Extension->DeviceClassSymbolicName.Buffer) {
  2822. status = IoSetDeviceInterfaceState(&Extension->DeviceClassSymbolicName,
  2823. FALSE);
  2824. //
  2825. // IoRegisterDeviceClassInterface() allocated this string for us,
  2826. // and we no longer need it.
  2827. //
  2828. ExFreePool(Extension->DeviceClassSymbolicName.Buffer);
  2829. Extension->DeviceClassSymbolicName.Buffer = NULL;
  2830. }
  2831. //
  2832. // Before we delete the symlink, re-read the PortName
  2833. // from the registry in case we were renamed in user mode.
  2834. //
  2835. status = IoOpenDeviceRegistryKey(Extension->Pdo, PLUGPLAY_REGKEY_DEVICE,
  2836. STANDARD_RIGHTS_READ, &keyHandle);
  2837. if (status == STATUS_SUCCESS) {
  2838. UNICODE_STRING symLinkName;
  2839. PWCHAR pRegName;
  2840. RtlInitUnicodeString(&symLinkName, NULL);
  2841. status = CyzReadSymName(Extension, keyHandle, &symLinkName,
  2842. &pRegName);
  2843. if (status == STATUS_SUCCESS) {
  2844. CyzDbgPrintEx(CYZDIAG1, "Deleting Link %wZ\n", &symLinkName);
  2845. IoDeleteSymbolicLink(&symLinkName);
  2846. ExFreePool(symLinkName.Buffer);
  2847. ExFreePool(pRegName);
  2848. }
  2849. ZwClose(keyHandle);
  2850. }
  2851. }
  2852. if (Extension->WmiIdentifier.Buffer) {
  2853. ExFreePool(Extension->WmiIdentifier.Buffer);
  2854. Extension->WmiIdentifier.MaximumLength
  2855. = Extension->WmiIdentifier.Length = 0;
  2856. Extension->WmiIdentifier.Buffer = NULL;
  2857. }
  2858. //
  2859. // We're cleaning up here. One reason we're cleaning up
  2860. // is that we couldn't allocate space for the NtNameOfPort.
  2861. //
  2862. if ((Extension->DeviceName.Buffer != NULL)
  2863. && Extension->CreatedSerialCommEntry) {
  2864. status = RtlDeleteRegistryValue(RTL_REGISTRY_DEVICEMAP, SERIAL_DEVICE_MAP,
  2865. Extension->DeviceName.Buffer);
  2866. //************************************
  2867. //Error Injection
  2868. //status = STATUS_INVALID_PARAMETER;
  2869. //************************************
  2870. if (!NT_SUCCESS(status)) {
  2871. CyzLogError(
  2872. Extension->DeviceObject->DriverObject,
  2873. Extension->DeviceObject,
  2874. Extension->OriginalBoardMemory,
  2875. CyzPhysicalZero,
  2876. 0,
  2877. 0,
  2878. 0,
  2879. Extension->PortIndex+1,
  2880. status,
  2881. CYZ_NO_DEVICE_MAP_DELETED,
  2882. Extension->DeviceName.Length+sizeof(WCHAR),
  2883. Extension->DeviceName.Buffer,
  2884. 0,
  2885. NULL
  2886. );
  2887. CyzDbgPrintEx(CYZERRORS, "Couldn't delete value entry %wZ\n",
  2888. &Extension->DeviceName);
  2889. }
  2890. }
  2891. }