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.

3819 lines
112 KiB

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