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.

1119 lines
35 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. pnp.c
  5. Abstract:
  6. This module contains plug & play code for the inport mouse
  7. Environment:
  8. Kernel & user mode.
  9. Revision History:
  10. Feb-1998 : Initial writing, Doron Holan
  11. --*/
  12. #include "inport.h"
  13. #include "inplog.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE, InportAddDevice)
  16. #pragma alloc_text(PAGE, InportPnP)
  17. #endif
  18. NTSTATUS
  19. InportAddDevice (
  20. IN PDRIVER_OBJECT Driver,
  21. IN PDEVICE_OBJECT PDO
  22. )
  23. /*++
  24. Routine Description:
  25. Arguments:
  26. Return Value:
  27. NTSTATUS result code.
  28. --*/
  29. {
  30. NTSTATUS status = STATUS_SUCCESS;
  31. PDEVICE_EXTENSION deviceExtension;
  32. PDEVICE_OBJECT device;
  33. PAGED_CODE();
  34. status = IoCreateDevice(Driver,
  35. sizeof(DEVICE_EXTENSION),
  36. NULL, // no name for this Filter DO
  37. FILE_DEVICE_INPORT_PORT,
  38. 0,
  39. FALSE,
  40. &device);
  41. if (!NT_SUCCESS(status)) {
  42. return status;
  43. }
  44. deviceExtension = (PDEVICE_EXTENSION) device->DeviceExtension;
  45. //
  46. // Initialize the fields.
  47. //
  48. RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION));
  49. deviceExtension->TopOfStack = IoAttachDeviceToDeviceStack(device, PDO);
  50. if (deviceExtension->TopOfStack == NULL) {
  51. PIO_ERROR_LOG_PACKET errorLogEntry;
  52. //
  53. // Not good; in only extreme cases will this fail
  54. //
  55. errorLogEntry = (PIO_ERROR_LOG_PACKET)
  56. IoAllocateErrorLogEntry(Driver,
  57. (UCHAR) sizeof(IO_ERROR_LOG_PACKET));
  58. if (errorLogEntry) {
  59. errorLogEntry->ErrorCode = INPORT_ATTACH_DEVICE_FAILED;
  60. errorLogEntry->DumpDataSize = 0;
  61. errorLogEntry->SequenceNumber = 0;
  62. errorLogEntry->MajorFunctionCode = 0;
  63. errorLogEntry->IoControlCode = 0;
  64. errorLogEntry->RetryCount = 0;
  65. errorLogEntry->UniqueErrorValue = 0;
  66. errorLogEntry->FinalStatus = STATUS_DEVICE_NOT_CONNECTED;
  67. IoWriteErrorLogEntry(errorLogEntry);
  68. }
  69. IoDeleteDevice(device);
  70. return STATUS_DEVICE_NOT_CONNECTED;
  71. }
  72. ASSERT(deviceExtension->TopOfStack);
  73. deviceExtension->Self = device;
  74. deviceExtension->Removed = FALSE;
  75. deviceExtension->Started = FALSE;
  76. deviceExtension->UnitId = 0;
  77. IoInitializeRemoveLock (&deviceExtension->RemoveLock, INP_POOL_TAG, 1, 10);
  78. #if defined(NEC_98)
  79. deviceExtension->PowerState = PowerDeviceD0;
  80. #endif // defined(NEC_98)
  81. //
  82. // Initialize WMI
  83. //
  84. deviceExtension->WmiLibInfo.GuidCount = sizeof(WmiGuidList) /
  85. sizeof(WMIGUIDREGINFO);
  86. deviceExtension->WmiLibInfo.GuidList = WmiGuidList;
  87. deviceExtension->WmiLibInfo.QueryWmiRegInfo = InportQueryWmiRegInfo;
  88. deviceExtension->WmiLibInfo.QueryWmiDataBlock = InportQueryWmiDataBlock;
  89. deviceExtension->WmiLibInfo.SetWmiDataBlock = InportSetWmiDataBlock;
  90. deviceExtension->WmiLibInfo.SetWmiDataItem = InportSetWmiDataItem;
  91. deviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
  92. deviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
  93. IoWMIRegistrationControl(deviceExtension->Self,
  94. WMIREG_ACTION_REGISTER
  95. );
  96. deviceExtension->PDO = PDO;
  97. device->Flags &= ~DO_DEVICE_INITIALIZING;
  98. device->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
  99. return status;
  100. }
  101. BOOLEAN
  102. InpReleaseResourcesEx(
  103. PVOID Context
  104. )
  105. {
  106. PDEVICE_EXTENSION deviceExtension = Context;
  107. KeRemoveQueueDpc(&deviceExtension->IsrDpc);
  108. KeRemoveQueueDpc(&deviceExtension->IsrDpcRetry);
  109. KeRemoveQueueDpc(&deviceExtension->ErrorLogDpc);
  110. // KeCancelTimer(&deviceExtension->DataConsumptionTimer);
  111. if (deviceExtension->Configuration.UnmapRegistersRequired) {
  112. MmUnmapIoSpace(deviceExtension->Configuration.DeviceRegisters[0],
  113. deviceExtension->Configuration.PortList[0].u.Port.Length);
  114. }
  115. //
  116. // Clear out the config info. If we get started again, than it will be filled
  117. // in again. If is from a remove, then it is essentially a no-op
  118. //
  119. RtlZeroMemory(&deviceExtension->Configuration,
  120. sizeof(INPORT_CONFIGURATION_INFORMATION));
  121. return TRUE;
  122. }
  123. VOID
  124. InpReleaseResources(
  125. PDEVICE_EXTENSION DeviceExtension
  126. )
  127. {
  128. InpPrint((2, "INPORT-InpReleaseResources: Enter\n"));
  129. if (DeviceExtension->InterruptObject) {
  130. KeSynchronizeExecution(
  131. DeviceExtension->InterruptObject,
  132. InpReleaseResourcesEx,
  133. (PVOID) DeviceExtension);
  134. IoDisconnectInterrupt(DeviceExtension->InterruptObject);
  135. DeviceExtension->InterruptObject = NULL;
  136. }
  137. else {
  138. InpReleaseResourcesEx((PVOID) DeviceExtension);
  139. }
  140. InpPrint((2, "INPORT-InpReleaseResources: Exit\n"));
  141. }
  142. NTSTATUS
  143. InpPnPComplete (
  144. IN PDEVICE_OBJECT DeviceObject,
  145. IN PIRP Irp,
  146. IN PVOID Context
  147. )
  148. /*++
  149. Routine Description:
  150. The pnp IRP is in the process of completing.
  151. signal
  152. Arguments:
  153. Context set to the device object in question.
  154. --*/
  155. {
  156. PIO_STACK_LOCATION stack;
  157. NTSTATUS status;
  158. PKEVENT event;
  159. InpPrint((2, "INPORT-InpPnPComplete: Enter\n"));
  160. status = STATUS_SUCCESS;
  161. event = (PKEVENT) Context;
  162. stack = IoGetCurrentIrpStackLocation(Irp);
  163. if (Irp->PendingReturned) {
  164. IoMarkIrpPending(Irp);
  165. }
  166. KeSetEvent(event,
  167. 0,
  168. FALSE);
  169. InpPrint((2, "INPORT-InpPnPComplete: Exit\n"));
  170. return STATUS_MORE_PROCESSING_REQUIRED;
  171. }
  172. NTSTATUS
  173. InportPnP (
  174. IN PDEVICE_OBJECT DeviceObject,
  175. IN PIRP Irp
  176. )
  177. /*++
  178. Routine Description:
  179. The plug and play dispatch routines.
  180. Most of these this filter driver will completely ignore.
  181. In all cases it must pass on the IRP to the lower driver.
  182. Arguments:
  183. DeviceObject - pointer to a device object.
  184. Irp - pointer to an I/O Request Packet.
  185. Return Value:
  186. NT status code
  187. --*/
  188. {
  189. PDEVICE_EXTENSION deviceExtension;
  190. PIO_STACK_LOCATION stack;
  191. NTSTATUS status;
  192. KEVENT event;
  193. PAGED_CODE();
  194. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  195. stack = IoGetCurrentIrpStackLocation(Irp);
  196. status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
  197. if (!NT_SUCCESS(status)) {
  198. //
  199. // Someone gave us a pnp irp after a remove. Unthinkable!
  200. //
  201. ASSERT(FALSE);
  202. Irp->IoStatus.Information = 0;
  203. Irp->IoStatus.Status = status;
  204. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  205. return status;
  206. }
  207. InpPrint((2, "INPORT-InportPnP: Enter (min func=0x%x)\n", stack->MinorFunction));
  208. switch (stack->MinorFunction) {
  209. case IRP_MN_START_DEVICE:
  210. #if defined(NEC_98)
  211. Globals.DeviceObject = (PDEVICE_OBJECT)DeviceObject;
  212. #endif // defined(NEC_98)
  213. //
  214. // If we have been started (and not stopped), then just ignore this start
  215. //
  216. if (deviceExtension->Started) {
  217. IoSkipCurrentIrpStackLocation(Irp);
  218. status = IoCallDriver(deviceExtension->TopOfStack, Irp);
  219. break;
  220. }
  221. //
  222. // Not allowed to touch the hardware until all of the lower DO's have
  223. // had a chance to look at it
  224. //
  225. IoCopyCurrentIrpStackLocationToNext(Irp);
  226. KeInitializeEvent(&event,
  227. NotificationEvent,
  228. FALSE
  229. );
  230. IoSetCompletionRoutine(Irp,
  231. (PIO_COMPLETION_ROUTINE) InpPnPComplete,
  232. &event,
  233. TRUE,
  234. TRUE,
  235. TRUE);
  236. status = IoCallDriver(deviceExtension->TopOfStack, Irp);
  237. if (STATUS_PENDING == status) {
  238. KeWaitForSingleObject(
  239. &event,
  240. Executive, // Waiting for reason of a driver
  241. KernelMode, // Waiting in kernel mode
  242. FALSE, // No alert
  243. NULL); // No timeout
  244. }
  245. if (NT_SUCCESS (status) && NT_SUCCESS (Irp->IoStatus.Status)) {
  246. status = InpStartDevice(
  247. DeviceObject->DeviceExtension,
  248. stack->Parameters.StartDevice.AllocatedResourcesTranslated);
  249. if (NT_SUCCESS(status)) {
  250. deviceExtension->Started = TRUE;
  251. }
  252. }
  253. //
  254. // We must now complete the IRP, since we stopped it in the
  255. // completetion routine with MORE_PROCESSING_REQUIRED.
  256. //
  257. Irp->IoStatus.Status = status;
  258. Irp->IoStatus.Information = 0;
  259. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  260. break;
  261. //
  262. // PnP rules dictate we send the IRP down to the PDO first
  263. //
  264. case IRP_MN_CANCEL_REMOVE_DEVICE:
  265. case IRP_MN_CANCEL_STOP_DEVICE:
  266. status = InpSendIrpSynchronously(deviceExtension->TopOfStack, Irp);
  267. Irp->IoStatus.Status = status;
  268. Irp->IoStatus.Information = 0;
  269. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  270. break;
  271. case IRP_MN_REMOVE_DEVICE:
  272. //
  273. // The PlugPlay system has dictacted the removal of this device. We
  274. // have no choise but to detach and delete the device objecct.
  275. // (If we wanted to express and interest in preventing this removal,
  276. // we should have filtered the query remove and query stop routines.)
  277. //
  278. // Note! we might receive a remove WITHOUT first receiving a stop.
  279. //
  280. InpPrint((2, "INPORT-InportPnP: remove device \n"));
  281. deviceExtension->Removed = TRUE;
  282. //
  283. // Here if we had any outstanding requests in a personal queue we should
  284. // complete them all now.
  285. //
  286. // Note, the device could be GONE so we cannot send it any non-
  287. // PNP IRPS.
  288. //
  289. InpReleaseResources(deviceExtension);
  290. //
  291. // Perform specific operations for a remove
  292. //
  293. IoWMIRegistrationControl(deviceExtension->Self,
  294. WMIREG_ACTION_DEREGISTER
  295. );
  296. //
  297. // Send on the remove IRP
  298. //
  299. IoSkipCurrentIrpStackLocation(Irp);
  300. status = IoCallDriver(deviceExtension->TopOfStack, Irp);
  301. //
  302. // Wait for the remove lock to free.
  303. //
  304. IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);
  305. IoDetachDevice(deviceExtension->TopOfStack);
  306. IoDeleteDevice(deviceExtension->Self);
  307. InpPrint((2, "INPORT-InportPnP: exit (%x)\n", STATUS_SUCCESS));
  308. return STATUS_SUCCESS;
  309. // NOTE:
  310. // handle this case if you want to add/remove resources that will be given
  311. // during start device. Add resources before passing the irp down.
  312. // Remove resources when the irp is coming back up
  313. // See dd\input\pnpi8042\pnp.c, I8xFilterResourceRequirements for an example
  314. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
  315. #if !defined(NEC_98)
  316. status = InpSendIrpSynchronously(deviceExtension->TopOfStack, Irp);
  317. //
  318. // If the lower filter does not support this Irp, this is
  319. // OK, we can ignore this error
  320. //
  321. if (status == STATUS_NOT_SUPPORTED) {
  322. status = STATUS_SUCCESS;
  323. }
  324. InpFilterResourceRequirements(DeviceObject, Irp);
  325. if (!NT_SUCCESS(status)) {
  326. InpPrint((2, "error pending filter res req event (0x%x)\n", status));
  327. }
  328. //
  329. // Irp->IoStatus.Information will contain the new i/o resource
  330. // requirements list so leave it alone
  331. //
  332. Irp->IoStatus.Status = status;
  333. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  334. break;
  335. #else
  336. InpPrint((2, "INPORT-InportPnP: IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"));
  337. #endif
  338. case IRP_MN_QUERY_REMOVE_DEVICE:
  339. case IRP_MN_QUERY_STOP_DEVICE:
  340. #if defined(NEC_98)
  341. //
  342. // Don't let either of the requests succeed, otherwise the mouse might be rendered useless.
  343. //
  344. status = STATUS_UNSUCCESSFUL;
  345. Irp->IoStatus.Status = status;
  346. Irp->IoStatus.Information = 0;
  347. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  348. break;
  349. #endif
  350. case IRP_MN_STOP_DEVICE:
  351. case IRP_MN_QUERY_DEVICE_RELATIONS:
  352. case IRP_MN_QUERY_INTERFACE:
  353. case IRP_MN_QUERY_CAPABILITIES:
  354. case IRP_MN_QUERY_DEVICE_TEXT:
  355. case IRP_MN_QUERY_RESOURCES:
  356. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  357. case IRP_MN_READ_CONFIG:
  358. case IRP_MN_WRITE_CONFIG:
  359. case IRP_MN_EJECT:
  360. case IRP_MN_SET_LOCK:
  361. case IRP_MN_QUERY_ID:
  362. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  363. default:
  364. //
  365. // Here the filter driver might modify the behavior of these IRPS
  366. // Please see PlugPlay documentation for use of these IRPs.
  367. //
  368. IoSkipCurrentIrpStackLocation(Irp);
  369. status = IoCallDriver(deviceExtension->TopOfStack, Irp);
  370. break;
  371. }
  372. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  373. InpPrint((2, "INPORT-InportPnP: exit (%x)\n", status));
  374. return status;
  375. }
  376. NTSTATUS
  377. InportPower (
  378. IN PDEVICE_OBJECT DeviceObject,
  379. IN PIRP Irp
  380. )
  381. /*++
  382. NOTE:
  383. You must write power code!!!
  384. System power irps can be ignored.
  385. Device power irps will be sent by mouclass. The transition from D0 to some
  386. lower usually involves doing nothing (maybe power down h/w if you have control
  387. over this). The transition from a lower power state to D0 must be handled by
  388. reinitializing the device.
  389. Please read http://titanic for Power documentation (especially on the use
  390. of PoCallDriver and PoStartNextPowerIrp)
  391. --*/
  392. {
  393. PIO_STACK_LOCATION stack;
  394. NTSTATUS status;
  395. PDEVICE_EXTENSION deviceExtension;
  396. POWER_STATE powerState;
  397. POWER_STATE_TYPE powerType;
  398. InpPrint((2, "INPORT-InportPower: Enter\n"));
  399. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  400. stack = IoGetCurrentIrpStackLocation(Irp);
  401. powerType = stack->Parameters.Power.Type;
  402. powerState = stack->Parameters.Power.State;
  403. status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
  404. if (!NT_SUCCESS(status)) {
  405. PoStartNextPowerIrp(Irp);
  406. Irp->IoStatus.Status = status;
  407. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  408. return status;
  409. }
  410. switch (stack->MinorFunction) {
  411. case IRP_MN_SET_POWER:
  412. InpPrint((2, "INPORT-InportPower: Power Setting %s state to %d\n",
  413. ((powerType == SystemPowerState) ? "System"
  414. : "Device"),
  415. powerState.SystemState));
  416. #if defined(NEC_98)
  417. //
  418. // Don't handle anything but DevicePowerState changes
  419. //
  420. if (stack->Parameters.Power.Type != DevicePowerState) {
  421. InpPrint((2,"INPORT-InportPower: not a device power irp\n"));
  422. break;
  423. }
  424. //
  425. // Check for no change in state, and if none, do nothing
  426. //
  427. if (stack->Parameters.Power.State.DeviceState ==
  428. deviceExtension->PowerState) {
  429. InpPrint((2,"INPORT-InportPower: no change in state (PowerDeviceD%d)\n",
  430. deviceExtension->PowerState-1
  431. ));
  432. break;
  433. }
  434. switch (stack->Parameters.Power.State.DeviceState) {
  435. case PowerDeviceD0:
  436. InpPrint((2,"INPORT-InportPower: Powering up to PowerDeviceD0\n"));
  437. IoCopyCurrentIrpStackLocationToNext(Irp);
  438. IoSetCompletionRoutine(Irp,
  439. InportPowerUpToD0Complete,
  440. NULL,
  441. TRUE, // on success
  442. TRUE, // on error
  443. TRUE // on cancel
  444. );
  445. //
  446. // PoStartNextPowerIrp() gets called in InportPowerUpToD0Complete
  447. //
  448. return PoCallDriver(deviceExtension->TopOfStack, Irp);
  449. case PowerDeviceD1:
  450. case PowerDeviceD2:
  451. case PowerDeviceD3:
  452. InpPrint((
  453. 2,"INPORT-InportPower: Powering down to PowerDeviceD%d\n",
  454. stack->Parameters.Power.State.DeviceState-1
  455. ));
  456. PoSetPowerState(DeviceObject,
  457. stack->Parameters.Power.Type,
  458. stack->Parameters.Power.State
  459. );
  460. deviceExtension->PowerState = stack->Parameters.Power.State.DeviceState;
  461. //
  462. // For what we are doing, we don't need a completion routine
  463. // since we don't race on the power requests.
  464. //
  465. Irp->IoStatus.Status = STATUS_SUCCESS;
  466. IoCopyCurrentIrpStackLocationToNext(Irp);
  467. PoStartNextPowerIrp(Irp);
  468. return PoCallDriver(deviceExtension->TopOfStack, Irp);
  469. default:
  470. InpPrint((2,"INPORT-InportPower: unknown state\n"));
  471. break;
  472. }
  473. break;
  474. #else // defined(NEC_98)
  475. break;
  476. #endif // defined(NEC_98)
  477. case IRP_MN_QUERY_POWER:
  478. InpPrint((2, "INPORT-InportPower: Power query %s status to %d\n",
  479. ((powerType == SystemPowerState) ? "System"
  480. : "Device"),
  481. powerState.SystemState));
  482. break;
  483. default:
  484. InpPrint((2, "INPORT-InportPower: Power minor (0x%x) no known\n", stack->MinorFunction));
  485. }
  486. PoStartNextPowerIrp(Irp);
  487. IoSkipCurrentIrpStackLocation(Irp);
  488. PoCallDriver(deviceExtension->TopOfStack, Irp);
  489. IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
  490. InpPrint((2, "INPORT-InportPower: Exit\n"));
  491. return STATUS_SUCCESS;
  492. }
  493. #if !defined(NEC_98)
  494. VOID
  495. InpFilterResourceRequirements(
  496. IN PDEVICE_OBJECT DeviceObject,
  497. IN PIRP Irp
  498. )
  499. /*++
  500. Routine Description:
  501. Iterates through the resource requirements list contained in the IRP and removes
  502. any duplicate requests for I/O ports. (This is a common problem on the Alphas.)
  503. No removal is performed if more than one resource requirements list is present.
  504. Arguments:
  505. DeviceObject - A pointer to the device object
  506. Irp - A pointer to the request packet which contains the resource req. list.
  507. Return Value:
  508. None.
  509. --*/
  510. {
  511. NTSTATUS status;
  512. PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  513. PCM_RESOURCE_LIST AllocatedResources;
  514. PIO_RESOURCE_REQUIREMENTS_LIST pReqList = NULL,
  515. newReqList = NULL;
  516. PIO_RESOURCE_LIST pResList = NULL,
  517. pNewResList = NULL;
  518. PIO_RESOURCE_DESCRIPTOR pResDesc = NULL,
  519. pNewResDesc = NULL;
  520. ULONG i = 0, reqCount, size = 0;
  521. BOOLEAN foundInt = FALSE, foundPorts = FALSE;
  522. PIO_STACK_LOCATION stack;
  523. INTERFACE_TYPE interfaceType = Isa;
  524. ULONG busNumber = 0;
  525. CONFIGURATION_TYPE controllerType = PointerController;
  526. CONFIGURATION_TYPE peripheralType = PointerPeripheral;
  527. PAGED_CODE();
  528. ASSERT(DeviceObject);
  529. ASSERT(DeviceObject->DeviceExtension);
  530. InpPrint((1, "Received IRP_MN_FILTER_RESOURCE_REQUIREMENTS for Inport\n"));
  531. stack = IoGetCurrentIrpStackLocation(Irp);
  532. //
  533. // The list can be in either the information field, or in the current
  534. // stack location. The Information field has a higher precedence over
  535. // the stack location.
  536. //
  537. if (Irp->IoStatus.Information == 0) {
  538. pReqList =
  539. stack->Parameters.FilterResourceRequirements.IoResourceRequirementList;
  540. Irp->IoStatus.Information = (ULONG_PTR) pReqList;
  541. }
  542. else {
  543. pReqList = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
  544. }
  545. if (!pReqList) {
  546. //
  547. // Not much can be done here except return
  548. //
  549. InpPrint((1, "NULL resource list in InpFilterResourceRequirements\n"));
  550. return;
  551. }
  552. ASSERT(Irp->IoStatus.Information != 0);
  553. ASSERT(pReqList != 0);
  554. reqCount = pReqList->AlternativeLists;
  555. //
  556. // Only one AlternativeList is supported. If there is more than one list,
  557. // then there is now way of knowing which list will be chosen. Also, if
  558. // there are multiple lists, then chances are that a list with no i/o port
  559. // conflicts will be chosen.
  560. //
  561. if (reqCount > 1) {
  562. return;
  563. }
  564. pResList = &pReqList->List[0];
  565. for (i = 0; i < pResList->Count; i++) {
  566. pResDesc = &pResList->Descriptors[i];
  567. switch (pResDesc->Type) {
  568. case CmResourceTypePort:
  569. foundPorts = TRUE;
  570. break;
  571. case CmResourceTypeInterrupt:
  572. foundInt = TRUE;
  573. break;
  574. default:
  575. break;
  576. }
  577. }
  578. if (!foundPorts && !foundInt)
  579. size = pReqList->ListSize + 2 * sizeof(IO_RESOURCE_DESCRIPTOR);
  580. else if (!foundPorts || !foundInt)
  581. size = pReqList->ListSize + sizeof(IO_RESOURCE_DESCRIPTOR);
  582. else {
  583. //
  584. // Nothing to filter, just leave
  585. //
  586. ASSERT(foundPorts);
  587. ASSERT(foundInt);
  588. return;
  589. }
  590. ASSERT(size != 0);
  591. newReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)
  592. ExAllocatePool(
  593. NonPagedPool,
  594. size
  595. );
  596. if (!newReqList) {
  597. return;
  598. }
  599. //
  600. // Clear out the newly allocated list
  601. //
  602. RtlZeroMemory(newReqList,
  603. size
  604. );
  605. //
  606. // Copy the entire old list
  607. //
  608. RtlCopyMemory(newReqList,
  609. pReqList,
  610. pReqList->ListSize
  611. );
  612. pResList = &newReqList->List[0];
  613. if (!foundPorts) {
  614. pResDesc = &pResList->Descriptors[pResList->Count++];
  615. pResDesc->Type = CmResourceTypePort;
  616. }
  617. if (!foundInt) {
  618. pResDesc = &pResList->Descriptors[pResList->Count++];
  619. pResDesc->Type = CmResourceTypeInterrupt;
  620. }
  621. pResList = &newReqList->List[0];
  622. interfaceType = Isa;
  623. status = IoQueryDeviceDescription(
  624. &interfaceType,
  625. &busNumber,
  626. &controllerType,
  627. NULL,
  628. &peripheralType,
  629. NULL,
  630. InpFindResourcesCallout,
  631. (PVOID) pResList
  632. );
  633. if (!NT_SUCCESS(status)) { // fill in with defaults
  634. PINPORT_CONFIGURATION_INFORMATION configuration = &deviceExtension->Configuration;
  635. ULONG InterruptLevel;
  636. InpPrint((1, "Failed IoQueryDeviceDescription, status = 0x%x\n...try the registry...\n", status));
  637. InpServiceParameters(deviceExtension,
  638. &Globals.RegistryPath);
  639. InterruptLevel = configuration->MouseInterrupt.u.Interrupt.Level;
  640. pResList = &newReqList->List[0];
  641. for (i = 0; i < pResList->Count; i++) {
  642. pResDesc = &pResList->Descriptors[i];
  643. switch (pResDesc->Type) {
  644. case CmResourceTypePort:
  645. if (foundPorts) break;
  646. pResDesc->Option = 0; // fixed resources
  647. pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
  648. pResDesc->Flags = CM_RESOURCE_PORT_IO;
  649. pResDesc->u.Port.Length = INP_DEF_PORT_SPAN;
  650. pResDesc->u.Port.Alignment = 1;
  651. pResDesc->u.Port.MinimumAddress.HighPart = 0;
  652. pResDesc->u.Port.MinimumAddress.LowPart = INP_DEF_PORT;
  653. pResDesc->u.Port.MaximumAddress.HighPart = 0;
  654. pResDesc->u.Port.MaximumAddress.LowPart = INP_DEF_PORT+INP_DEF_PORT_SPAN-1;
  655. break;
  656. case CmResourceTypeInterrupt:
  657. if (foundInt) break;
  658. pResDesc->Option = 0; // fixed resources
  659. pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
  660. pResDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED; //Isa
  661. pResDesc->u.Interrupt.MinimumVector = InterruptLevel;
  662. pResDesc->u.Interrupt.MaximumVector = InterruptLevel;
  663. break;
  664. default:
  665. break;
  666. }
  667. }
  668. }
  669. newReqList->ListSize = size;
  670. //
  671. // Free the old list and place the new one in its place
  672. //
  673. ExFreePool(pReqList);
  674. stack->Parameters.FilterResourceRequirements.IoResourceRequirementList =
  675. newReqList;
  676. Irp->IoStatus.Information = (ULONG_PTR) newReqList;
  677. }
  678. NTSTATUS
  679. InpFindResourcesCallout(
  680. IN PVOID Context,
  681. IN PUNICODE_STRING PathName,
  682. IN INTERFACE_TYPE BusType,
  683. IN ULONG BusNumber,
  684. IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
  685. IN CONFIGURATION_TYPE ControllerType,
  686. IN ULONG ControllerNumber,
  687. IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
  688. IN CONFIGURATION_TYPE PeripheralType,
  689. IN ULONG PeripheralNumber,
  690. IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
  691. )
  692. /*++
  693. Routine Description:
  694. This is the callout routine sent as a parameter to
  695. IoQueryDeviceDescription. It grabs the keyboard controller and
  696. peripheral configuration information.
  697. Arguments:
  698. Context - Context parameter that was passed in by the routine
  699. that called IoQueryDeviceDescription.
  700. PathName - The full pathname for the registry key.
  701. BusType - Bus interface type (Isa, Eisa, Mca, etc.).
  702. BusNumber - The bus sub-key (0, 1, etc.).
  703. BusInformation - Pointer to the array of pointers to the full value
  704. information for the bus.
  705. ControllerType - The controller type (should be KeyboardController).
  706. ControllerNumber - The controller sub-key (0, 1, etc.).
  707. ControllerInformation - Pointer to the array of pointers to the full
  708. value information for the controller key.
  709. PeripheralType - The peripheral type (should be KeyboardPeripheral).
  710. PeripheralNumber - The peripheral sub-key.
  711. PeripheralInformation - Pointer to the array of pointers to the full
  712. value information for the peripheral key.
  713. Return Value:
  714. None. If successful, will have the following side-effects:
  715. - Sets DeviceObject->DeviceExtension->HardwarePresent.
  716. - Sets configuration fields in
  717. DeviceObject->DeviceExtension->Configuration.
  718. --*/
  719. {
  720. PUCHAR controllerData;
  721. NTSTATUS status = STATUS_UNSUCCESSFUL;
  722. ULONG i,
  723. listCount,
  724. portCount = 0;
  725. PIO_RESOURCE_LIST pResList = (PIO_RESOURCE_LIST) Context;
  726. PIO_RESOURCE_DESCRIPTOR pResDesc;
  727. PKEY_VALUE_FULL_INFORMATION controllerInfo = NULL;
  728. PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor, PortResDesc = NULL, IntResDesc = NULL;
  729. BOOLEAN foundInt = FALSE,
  730. foundPorts = FALSE;
  731. PAGED_CODE();
  732. UNREFERENCED_PARAMETER(PathName);
  733. UNREFERENCED_PARAMETER(BusType);
  734. UNREFERENCED_PARAMETER(BusNumber);
  735. UNREFERENCED_PARAMETER(BusInformation);
  736. UNREFERENCED_PARAMETER(ControllerType);
  737. UNREFERENCED_PARAMETER(ControllerNumber);
  738. UNREFERENCED_PARAMETER(PeripheralType);
  739. UNREFERENCED_PARAMETER(PeripheralNumber);
  740. UNREFERENCED_PARAMETER(PeripheralInformation);
  741. pResDesc = pResList->Descriptors + pResList->Count;
  742. controllerInfo = ControllerInformation[IoQueryDeviceConfigurationData];
  743. InpPrint((2, "InpFindPortCallout enter\n"));
  744. if (controllerInfo->DataLength != 0) {
  745. controllerData = ((PUCHAR) controllerInfo) + controllerInfo->DataOffset;
  746. controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
  747. PartialResourceList);
  748. listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count;
  749. resourceDescriptor =
  750. ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors;
  751. for (i = 0; i < listCount; i++, resourceDescriptor++) {
  752. switch(resourceDescriptor->Type) {
  753. case CmResourceTypePort:
  754. PortResDesc = resourceDescriptor;
  755. break;
  756. case CmResourceTypeInterrupt:
  757. IntResDesc = resourceDescriptor;
  758. break;
  759. default:
  760. break;
  761. }
  762. }
  763. }
  764. for (i = 0; i < pResList->Count; i++) {
  765. pResDesc = &pResList->Descriptors[i];
  766. switch (pResDesc->Type) {
  767. case CmResourceTypePort:
  768. if (PortResDesc) {
  769. resourceDescriptor = PortResDesc;
  770. pResDesc->Option = 0; // fixed resources
  771. pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
  772. pResDesc->Flags = CM_RESOURCE_PORT_IO;
  773. pResDesc->u.Port.Alignment = 1;
  774. pResDesc->u.Port.Length = INP_DEF_PORT_SPAN;
  775. pResDesc->u.Port.MinimumAddress.QuadPart =
  776. resourceDescriptor->u.Port.Start.QuadPart;
  777. pResDesc->u.Port.MaximumAddress.QuadPart =
  778. pResDesc->u.Port.MinimumAddress.QuadPart +
  779. pResDesc->u.Port.Length - 1;
  780. }
  781. break;
  782. case CmResourceTypeInterrupt:
  783. if (IntResDesc) {
  784. resourceDescriptor = IntResDesc;
  785. pResDesc->Option = 0; // fixed resources
  786. pResDesc->ShareDisposition = INPORT_REGISTER_SHARE? CmResourceShareShared:CmResourceShareDeviceExclusive;
  787. pResDesc->Flags = CM_RESOURCE_INTERRUPT_LATCHED; //Isa
  788. pResDesc->u.Interrupt.MinimumVector = resourceDescriptor->u.Interrupt.Level;
  789. pResDesc->u.Interrupt.MaximumVector = resourceDescriptor->u.Interrupt.Level;
  790. }
  791. break;
  792. default:
  793. break;
  794. }
  795. }
  796. if (PortResDesc && IntResDesc)
  797. status = STATUS_SUCCESS;
  798. else
  799. status = STATUS_UNSUCCESSFUL;
  800. InpPrint((2, "InpFindPortCallout exit (0x%x)\n", status));
  801. return status;
  802. }
  803. #endif
  804. NTSTATUS
  805. InpSendIrpSynchronously (
  806. IN PDEVICE_OBJECT DeviceObject,
  807. IN PIRP Irp
  808. )
  809. {
  810. KEVENT event;
  811. NTSTATUS status;
  812. PAGED_CODE();
  813. KeInitializeEvent(&event,
  814. SynchronizationEvent,
  815. FALSE
  816. );
  817. IoCopyCurrentIrpStackLocationToNext(Irp);
  818. IoSetCompletionRoutine(Irp,
  819. InpPnPComplete,
  820. &event,
  821. TRUE,
  822. TRUE,
  823. TRUE
  824. );
  825. status = IoCallDriver(DeviceObject, Irp);
  826. //
  827. // Wait for lower drivers to be done with the Irp
  828. //
  829. if (status == STATUS_PENDING) {
  830. KeWaitForSingleObject(&event,
  831. Executive,
  832. KernelMode,
  833. FALSE,
  834. NULL
  835. );
  836. status = Irp->IoStatus.Status;
  837. }
  838. return status;
  839. }
  840. #if defined(NEC_98)
  841. NTSTATUS
  842. InportPowerUpToD0Complete(
  843. IN PDEVICE_OBJECT DeviceObject,
  844. IN PIRP Irp,
  845. IN PVOID Context
  846. )
  847. /*++
  848. Routine Description:
  849. Reinitializes the Inport Mouse haardware after any type of hibernation/sleep.
  850. Arguments:
  851. DeviceObject - Pointer to the device object
  852. Irp - Pointer to the request
  853. Context - Context passed in from the funciton that set the completion
  854. routine. UNUSED.
  855. Return Value:
  856. STATUS_SUCCESSFUL if successful,
  857. an valid NTSTATUS error code otherwise
  858. --*/
  859. {
  860. NTSTATUS status;
  861. PIO_STACK_LOCATION stack;
  862. PDEVICE_EXTENSION deviceExtension;
  863. PWORK_QUEUE_ITEM item;
  864. UNREFERENCED_PARAMETER(Context);
  865. deviceExtension = DeviceObject->DeviceExtension;
  866. status = Irp->IoStatus.Status;
  867. stack = IoGetCurrentIrpStackLocation(Irp);
  868. if (NT_SUCCESS(status)) {
  869. //
  870. // Reset the power state to powered up
  871. //
  872. deviceExtension->PowerState = PowerDeviceD0;
  873. //
  874. // Everything has been powered up, let the system know about it
  875. //
  876. PoSetPowerState(DeviceObject,
  877. stack->Parameters.Power.Type,
  878. stack->Parameters.Power.State
  879. );
  880. item = (PWORK_QUEUE_ITEM) ExAllocatePool(NonPagedPool,
  881. sizeof(WORK_QUEUE_ITEM));
  882. if (!item) {
  883. //
  884. // must elaborate here
  885. //
  886. return STATUS_INSUFFICIENT_RESOURCES;
  887. }
  888. ExInitializeWorkItem(item, InportReinitializeHardware, item);
  889. ExQueueWorkItem(item, DelayedWorkQueue);
  890. }
  891. InpPrint((2,"INPORT-InportPowerUpToD0Complete: PowerUpToD0Complete, exit\n"));
  892. PoStartNextPowerIrp(Irp);
  893. return status;
  894. }
  895. #endif // defined(NEC_98)