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.

1789 lines
52 KiB

  1. #if defined(i386)
  2. /*++
  3. Copyright (c) 1989, 1990, 1991, 1992, 1993 Microsoft Corporation
  4. Module Name:
  5. inpdep.c
  6. Abstract:
  7. The initialization and hardware-dependent portions of
  8. the Microsoft InPort mouse port driver. Modifications to
  9. support new mice similar to the InPort mouse should be
  10. localized to this file.
  11. Environment:
  12. Kernel mode only.
  13. Notes:
  14. NOTES: (Future/outstanding issues)
  15. - Powerfail not implemented.
  16. - Consolidate duplicate code, where possible and appropriate.
  17. Revision History:
  18. --*/
  19. #include "stdarg.h"
  20. #include "stdio.h"
  21. #include "string.h"
  22. #include "ntddk.h"
  23. #include "inport.h"
  24. #include "inplog.h"
  25. #if defined(NEC_98)
  26. ULONG EventStatus = 0;
  27. #endif // defined(NEC_98)
  28. //
  29. // Use the alloc_text pragma to specify the driver initialization routines
  30. // (they can be paged out).
  31. //
  32. #ifdef ALLOC_PRAGMA
  33. // #pragma alloc_text(INIT,InpConfiguration)
  34. // #pragma alloc_text(INIT,InpPeripheralCallout)
  35. // #pragma alloc_text(INIT,InpBuildResourceList)
  36. #pragma alloc_text(INIT,DriverEntry)
  37. #pragma alloc_text(PAGE,InpServiceParameters)
  38. #pragma alloc_text(PAGE,InpInitializeHardware)
  39. #if defined(NEC_98)
  40. #pragma alloc_text(INIT,QueryEventMode)
  41. #endif // defined(NEC_98)
  42. #endif
  43. GLOBALS Globals;
  44. NTSTATUS
  45. DriverEntry(
  46. IN PDRIVER_OBJECT DriverObject,
  47. IN PUNICODE_STRING RegistryPath
  48. )
  49. /*++
  50. Routine Description:
  51. This routine initializes the Inport mouse port driver.
  52. Arguments:
  53. DriverObject - Pointer to driver object created by system.
  54. RegistryPath - Pointer to the Unicode name of the registry path
  55. for this driver.
  56. Return Value:
  57. The function value is the final status from the initialization operation.
  58. --*/
  59. {
  60. NTSTATUS status = STATUS_SUCCESS;
  61. PIO_ERROR_LOG_PACKET errorLogEntry;
  62. NTSTATUS errorCode;
  63. ULONG uniqueErrorValue, dumpCount;
  64. #define NAME_MAX 256
  65. WCHAR nameBuffer[NAME_MAX];
  66. ULONG dumpData[4];
  67. InpPrint((1,"\n\nINPORT-InportDriverEntry: enter\n"));
  68. //
  69. // Need to ensure that the registry path is null-terminated.
  70. // Allocate pool to hold a null-terminated copy of the path.
  71. //
  72. Globals.RegistryPath.MaximumLength = 0;
  73. Globals.RegistryPath.Buffer = ExAllocatePool(
  74. PagedPool,
  75. RegistryPath->Length + sizeof(UNICODE_NULL)
  76. );
  77. if (!Globals.RegistryPath.Buffer) {
  78. InpPrint((
  79. 1,
  80. "INPORT-InportDriverEntry: Couldn't allocate pool for registry path\n"
  81. ));
  82. dumpData[0] = (ULONG) RegistryPath->Length + sizeof(UNICODE_NULL);
  83. dumpCount = 1;
  84. InpLogError(
  85. (PDEVICE_OBJECT)DriverObject,
  86. INPORT_INSUFFICIENT_RESOURCES,
  87. INPORT_ERROR_VALUE_BASE + 2,
  88. STATUS_UNSUCCESSFUL,
  89. dumpData,
  90. 1
  91. );
  92. } else {
  93. Globals.RegistryPath.Length = RegistryPath->Length + sizeof(UNICODE_NULL);
  94. Globals.RegistryPath.MaximumLength = Globals.RegistryPath.Length;
  95. RtlZeroMemory(
  96. Globals.RegistryPath.Buffer,
  97. Globals.RegistryPath.Length
  98. );
  99. RtlMoveMemory(
  100. Globals.RegistryPath.Buffer,
  101. RegistryPath->Buffer,
  102. RegistryPath->Length
  103. );
  104. }
  105. //
  106. // Set up the device driver entry points.
  107. //
  108. DriverObject->DriverStartIo = InportStartIo;
  109. DriverObject->DriverExtension->AddDevice = InportAddDevice;
  110. DriverObject->MajorFunction[IRP_MJ_CREATE] = InportCreate;
  111. DriverObject->MajorFunction[IRP_MJ_CLOSE] = InportClose;
  112. DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] =
  113. InportFlush;
  114. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  115. InportInternalDeviceControl;
  116. DriverObject->MajorFunction[IRP_MJ_PNP] = InportPnP;
  117. DriverObject->MajorFunction[IRP_MJ_POWER] = InportPower;
  118. //
  119. // NOTE: Don't allow this driver to unload. Otherwise, we would set
  120. // DriverObject->DriverUnload = InportUnload.
  121. //
  122. #if defined(NEC_98)
  123. //
  124. // Is "Event Interrupt Mode" available on this machine?
  125. //
  126. QueryEventMode();
  127. #endif // defined(NEC_98)
  128. InpPrint((1,"INPORT-InportDriverEntry: exit\n"));
  129. return(status);
  130. }
  131. BOOLEAN
  132. InportInterruptService(
  133. IN PKINTERRUPT Interrupt,
  134. IN PVOID Context
  135. )
  136. /*++
  137. Routine Description:
  138. This is the interrupt service routine for the mouse device.
  139. Arguments:
  140. Interrupt - A pointer to the interrupt object for this interrupt.
  141. Context - A pointer to the device object.
  142. Return Value:
  143. Returns TRUE if the interrupt was expected (and therefore processed);
  144. otherwise, FALSE is returned.
  145. --*/
  146. {
  147. PDEVICE_EXTENSION deviceExtension;
  148. PDEVICE_OBJECT deviceObject;
  149. PUCHAR port;
  150. UCHAR previousButtons;
  151. UCHAR mode;
  152. UCHAR status;
  153. #if defined(NEC_98)
  154. PINPORT_CONFIGURATION_INFORMATION Configuration;
  155. #endif // defined(NEC_98)
  156. UNREFERENCED_PARAMETER(Interrupt);
  157. InpPrint((3, "INPORT-InportInterruptService: enter\n"));
  158. //
  159. // Get the device extension.
  160. //
  161. deviceObject = (PDEVICE_OBJECT) Context;
  162. deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
  163. #if defined(NEC_98)
  164. Configuration = &deviceExtension->Configuration;
  165. if (Configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE) {
  166. if ((READ_PORT_UCHAR((PUCHAR)PC98_MOUSE_INT_SHARE_CHECK_PORT) & PC98_MOUSE_INT_SERVICE)
  167. != PC98_MOUSE_INT_SERVICE) {
  168. InpPrint((1, "InportInterruptService: exit [NOT Mouse Service]\n"));
  169. return(FALSE);
  170. }
  171. }
  172. if (deviceExtension->ConnectData.ClassService == NULL) {
  173. InpPrint((1, "InportInterruptService: exit [not connected yet]\n"));
  174. return(TRUE);
  175. }
  176. #endif // defined(NEC_98)
  177. //
  178. // Get the Inport mouse port address.
  179. //
  180. port = deviceExtension->Configuration.DeviceRegisters[0];
  181. #if defined(NEC_98)
  182. WRITE_PORT_UCHAR(port + PC98_WritePortC2, PC98_TimerIntDisable);
  183. //
  184. // Read X Data.
  185. //
  186. WRITE_PORT_UCHAR(port + PC98_WritePortC2, PC98_X_ReadCommandHi);
  187. status = (UCHAR)(LONG)(SCHAR) READ_PORT_UCHAR((PUCHAR)(port + PC98_ReadPortA));
  188. deviceExtension->CurrentInput.LastX = status & 0x000f;
  189. WRITE_PORT_UCHAR(port + PC98_WritePortC2, PC98_X_ReadCommandLow);
  190. deviceExtension->CurrentInput.LastX =
  191. (LONG)(SCHAR) ((deviceExtension->CurrentInput.LastX << 4) |
  192. (READ_PORT_UCHAR(port + PC98_ReadPortA) & 0x000f));
  193. //
  194. // Read Y Data.
  195. //
  196. WRITE_PORT_UCHAR(port + PC98_WritePortC2, PC98_Y_ReadCommandHi);
  197. status = (UCHAR)(LONG)(SCHAR) READ_PORT_UCHAR((PUCHAR)(port + PC98_ReadPortA));
  198. deviceExtension->CurrentInput.LastY = status & 0x000f;
  199. WRITE_PORT_UCHAR(port + PC98_WritePortC2, PC98_Y_ReadCommandLow);
  200. deviceExtension->CurrentInput.LastY =
  201. (LONG)(SCHAR) ((deviceExtension->CurrentInput.LastY << 4) |
  202. (READ_PORT_UCHAR(port + PC98_ReadPortA) & 0x000f));
  203. //
  204. // Set Mouse Button Status.
  205. //
  206. status = ~status;
  207. #else // defined(NEC_98)
  208. //
  209. // Note: It would be nice to verify that the interrupt really
  210. // belongs to this driver, but it is currently not known how to
  211. // make that determination.
  212. //
  213. //
  214. // Set the Inport hold bit. Note that there is a bug in the 1.1 version
  215. // of the Inport chip in DATA mode. The interrupt signal doesn't get
  216. // cleared in some cases, thus effectively disabling the device. The
  217. // workaround is to set the HOLD bit twice.
  218. //
  219. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
  220. mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
  221. WRITE_PORT_UCHAR(
  222. (PUCHAR) (port + INPORT_DATA_REGISTER_1),
  223. (UCHAR) (mode | INPORT_MODE_HOLD)
  224. );
  225. WRITE_PORT_UCHAR(
  226. (PUCHAR) (port + INPORT_DATA_REGISTER_1),
  227. (UCHAR) (mode | INPORT_MODE_HOLD)
  228. );
  229. //
  230. // Read the Inport status register. It contains the following information:
  231. //
  232. // XXXXXXXX
  233. // | | |------ 1 if button 3 is down (right button)
  234. // | |-------- 1 if button 1 is down (left button)
  235. // |------------ 1 if the mouse has moved
  236. //
  237. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_STATUS_REGISTER);
  238. status = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
  239. InpPrint((3, "INPORT-InportInterruptService: status byte 0x%x\n", status));
  240. #endif // defined(NEC_98)
  241. //
  242. // Update CurrentInput with button transition data.
  243. // I.e., set a button up/down bit in the Buttons field if
  244. // the state of a given button has changed since we
  245. // received the last packet.
  246. //
  247. previousButtons =
  248. deviceExtension->PreviousButtons;
  249. deviceExtension->CurrentInput.Buttons = 0;
  250. if ((!(previousButtons & INPORT_STATUS_BUTTON1))
  251. && (status & INPORT_STATUS_BUTTON1)) {
  252. deviceExtension->CurrentInput.Buttons |=
  253. MOUSE_LEFT_BUTTON_DOWN;
  254. } else
  255. if ((previousButtons & INPORT_STATUS_BUTTON1)
  256. && !(status & INPORT_STATUS_BUTTON1)) {
  257. deviceExtension->CurrentInput.Buttons |=
  258. MOUSE_LEFT_BUTTON_UP;
  259. }
  260. if ((!(previousButtons & INPORT_STATUS_BUTTON3))
  261. && (status & INPORT_STATUS_BUTTON3)) {
  262. deviceExtension->CurrentInput.Buttons |=
  263. MOUSE_RIGHT_BUTTON_DOWN;
  264. } else
  265. if ((previousButtons & INPORT_STATUS_BUTTON3)
  266. && !(status & INPORT_STATUS_BUTTON3)) {
  267. deviceExtension->CurrentInput.Buttons |=
  268. MOUSE_RIGHT_BUTTON_UP;
  269. }
  270. //
  271. // If the button position changed or the mouse moved, continue to process
  272. // the interrupt. Otherwise, just clear the hold bit and ignore this
  273. // interrupt's data.
  274. //
  275. #if defined(NEC_98)
  276. if ((deviceExtension->PreviousButtons ^ deviceExtension->CurrentInput.Buttons)
  277. || (deviceExtension->CurrentInput.LastX | deviceExtension->CurrentInput.LastY)) {
  278. #else // defined(NEC_98)
  279. if (deviceExtension->CurrentInput.Buttons
  280. || (status & INPORT_STATUS_MOVEMENT)) {
  281. deviceExtension->CurrentInput.UnitId = deviceExtension->UnitId;
  282. #endif // defined(NEC_98)
  283. //
  284. // Keep track of the state of the mouse buttons for the next
  285. // interrupt.
  286. //
  287. deviceExtension->PreviousButtons =
  288. status & (INPORT_STATUS_BUTTON1 | INPORT_STATUS_BUTTON3);
  289. #if defined(NEC_98)
  290. //
  291. // If mouse not movement was recorded, set the X and Y motion 0 data.
  292. //
  293. if (!(deviceExtension->CurrentInput.LastX | deviceExtension->CurrentInput.LastY)) {
  294. deviceExtension->CurrentInput.LastX = 0;
  295. deviceExtension->CurrentInput.LastY = 0;
  296. }
  297. WRITE_PORT_UCHAR(port + PC98_WritePortC2, PC98_TimerIntEnable);
  298. #else // defined(NEC_98)
  299. //
  300. // If mouse movement was recorded, get the X and Y motion data.
  301. //
  302. if (status & INPORT_STATUS_MOVEMENT) {
  303. //
  304. // Select the Data1 register as the current data register, and
  305. // get the X motion byte.
  306. //
  307. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_DATA_REGISTER_1);
  308. deviceExtension->CurrentInput.LastX =
  309. (LONG)(SCHAR) READ_PORT_UCHAR(
  310. (PUCHAR) (port + INPORT_DATA_REGISTER_1));
  311. //
  312. // Select the Data2 register as the current data register, and
  313. // get the Y motion byte.
  314. //
  315. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_DATA_REGISTER_2);
  316. deviceExtension->CurrentInput.LastY =
  317. (LONG)(SCHAR) READ_PORT_UCHAR(
  318. (PUCHAR) (port + INPORT_DATA_REGISTER_1));
  319. } else {
  320. deviceExtension->CurrentInput.LastX = 0;
  321. deviceExtension->CurrentInput.LastY = 0;
  322. }
  323. //
  324. // Clear the Inport hold bit.
  325. //
  326. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
  327. mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
  328. WRITE_PORT_UCHAR(
  329. (PUCHAR) (port + INPORT_DATA_REGISTER_1),
  330. (UCHAR) (mode & ~INPORT_MODE_HOLD)
  331. );
  332. #endif // defined(NEC_98)
  333. //
  334. // Write the input data to the queue and request the ISR DPC to
  335. // finish processing the interrupt at DISPATCH_LEVEL.
  336. //
  337. if (!InpWriteDataToQueue(
  338. deviceExtension,
  339. &deviceExtension->CurrentInput
  340. )) {
  341. //
  342. // The mouse input data queue is full. Just drop the
  343. // latest input on the floor.
  344. //
  345. // Queue a DPC to log an overrun error.
  346. //
  347. InpPrint((
  348. 1,
  349. "INPORT-InportInterruptService: queue overflow\n"
  350. ));
  351. if (deviceExtension->OkayToLogOverflow) {
  352. KeInsertQueueDpc(
  353. &deviceExtension->ErrorLogDpc,
  354. (PIRP) NULL,
  355. (PVOID) (ULONG) INPORT_MOU_BUFFER_OVERFLOW
  356. );
  357. deviceExtension->OkayToLogOverflow = FALSE;
  358. }
  359. } else if (deviceExtension->DpcInterlockVariable >= 0) {
  360. //
  361. // The ISR DPC is already executing. Tell the ISR DPC it has
  362. // more work to do by incrementing the DpcInterlockVariable.
  363. //
  364. deviceExtension->DpcInterlockVariable += 1;
  365. } else {
  366. //
  367. // Queue the ISR DPC.
  368. //
  369. KeInsertQueueDpc(
  370. &deviceExtension->IsrDpc,
  371. deviceObject->CurrentIrp,
  372. NULL
  373. );
  374. }
  375. } else {
  376. InpPrint((
  377. 3,
  378. "INPORT-InportInterruptService: interrupt without button/motion change\n"
  379. ));
  380. //
  381. // Clear the Inport hold bit.
  382. //
  383. #if defined(NEC_98)
  384. WRITE_PORT_UCHAR(port + PC98_WritePortC2, PC98_TimerIntEnable);
  385. #else // defined(NEC_98)
  386. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
  387. mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
  388. WRITE_PORT_UCHAR(
  389. (PUCHAR) (port + INPORT_DATA_REGISTER_1),
  390. (UCHAR) (mode & ~INPORT_MODE_HOLD)
  391. );
  392. #endif // defined(NEC_98)
  393. }
  394. InpPrint((3, "INPORT-InportInterruptService: exit\n"));
  395. return(TRUE);
  396. }
  397. VOID
  398. InportUnload(
  399. IN PDRIVER_OBJECT DriverObject
  400. )
  401. {
  402. UNREFERENCED_PARAMETER(DriverObject);
  403. InpPrint((2, "INPORT-InportUnload: enter\n"));
  404. ExFreePool(Globals.RegistryPath.Buffer);
  405. InpPrint((2, "INPORT-InportUnload: exit\n"));
  406. }
  407. #define DUMP_COUNT 4
  408. NTSTATUS
  409. InpConfigureDevice(
  410. IN OUT PDEVICE_EXTENSION DeviceExtension,
  411. IN PCM_RESOURCE_LIST ResourceList
  412. )
  413. {
  414. PINPORT_CONFIGURATION_INFORMATION configuration;
  415. NTSTATUS status = STATUS_SUCCESS;
  416. ULONG i, count;
  417. BOOLEAN defaultInterruptShare;
  418. KINTERRUPT_MODE defaultInterruptMode;
  419. PCM_PARTIAL_RESOURCE_LIST partialResList = NULL;
  420. PCM_PARTIAL_RESOURCE_DESCRIPTOR currentResDesc = NULL;
  421. PCM_FULL_RESOURCE_DESCRIPTOR fullResDesc = NULL;
  422. configuration = &DeviceExtension->Configuration;
  423. if (!ResourceList) {
  424. InpPrint((1, "INPORT-InpConfigureDevice: mouse with null resources\n"));
  425. return STATUS_INSUFFICIENT_RESOURCES;
  426. }
  427. fullResDesc = ResourceList->List;
  428. if (!fullResDesc) {
  429. //
  430. // this should never happen
  431. //
  432. ASSERT(fullResDesc != NULL);
  433. return STATUS_INSUFFICIENT_RESOURCES;
  434. }
  435. partialResList = &fullResDesc->PartialResourceList;
  436. currentResDesc = partialResList->PartialDescriptors;
  437. count = partialResList->Count;
  438. configuration->BusNumber = fullResDesc->BusNumber;
  439. configuration->InterfaceType = fullResDesc->InterfaceType;
  440. configuration->FloatingSave = INPORT_FLOATING_SAVE;
  441. if (configuration->InterfaceType == MicroChannel) {
  442. defaultInterruptShare = TRUE;
  443. defaultInterruptMode = LevelSensitive;
  444. } else {
  445. defaultInterruptShare = INPORT_INTERRUPT_SHARE;
  446. defaultInterruptMode = INPORT_INTERRUPT_MODE;
  447. }
  448. DeviceExtension->Configuration.UnmapRegistersRequired = FALSE;
  449. //
  450. // Look through the resource list for interrupt and port
  451. // configuration information.
  452. //
  453. for (i = 0; i < count; i++, currentResDesc++) {
  454. switch(currentResDesc->Type) {
  455. case CmResourceTypePort:
  456. #if defined(NEC_98)
  457. //
  458. // Copy the port information. Note that we expect to
  459. // find more than one port ranges for the NEC98 Bus Mouse.
  460. //
  461. ASSERT(configuration->PortListCount < (sizeof(configuration->PortList) / sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)));
  462. #else // defined(NEC_98)
  463. //
  464. // Copy the port information. Note that we only expect to
  465. // find one port range for the Inport mouse.
  466. //
  467. ASSERT(configuration->PortListCount == 0);
  468. #endif // defined(NEC_98)
  469. configuration->PortList[configuration->PortListCount] =
  470. *currentResDesc;
  471. configuration->PortList[configuration->PortListCount].ShareDisposition =
  472. INPORT_REGISTER_SHARE? CmResourceShareShared:
  473. CmResourceShareDeviceExclusive;
  474. configuration->PortListCount += 1;
  475. if (currentResDesc->Flags == CM_RESOURCE_PORT_MEMORY) {
  476. DeviceExtension->Configuration.UnmapRegistersRequired = TRUE;
  477. }
  478. break;
  479. case CmResourceTypeInterrupt:
  480. //
  481. // Copy the interrupt information.
  482. //
  483. configuration->MouseInterrupt = *currentResDesc;
  484. configuration->MouseInterrupt.ShareDisposition =
  485. defaultInterruptShare? CmResourceShareShared :
  486. CmResourceShareDeviceExclusive;
  487. break;
  488. default:
  489. break;
  490. }
  491. }
  492. if (!(configuration->MouseInterrupt.Type & CmResourceTypeInterrupt)) {
  493. return STATUS_UNSUCCESSFUL;
  494. }
  495. #if defined(NEC_98)
  496. if (configuration->MouseInterrupt.Flags != CM_RESOURCE_INTERRUPT_LATCHED) {
  497. configuration->MouseInterrupt.ShareDisposition = CmResourceShareShared;
  498. }
  499. #endif // defined(NEC_98)
  500. InpPrint((
  501. 1,
  502. "INPORT-InpConfigureDevice: Mouse interrupt config --\n"
  503. ));
  504. InpPrint((
  505. 1,
  506. " %s, %s, Irq = %d\n",
  507. configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared?
  508. "Sharable" : "NonSharable",
  509. configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED?
  510. "Latched" : "Level Sensitive",
  511. configuration->MouseInterrupt.u.Interrupt.Vector
  512. ));
  513. //
  514. // Again, if we must check for this condition in IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  515. //
  516. #if 0
  517. //
  518. // If no port configuration information was found, use the
  519. // driver defaults.
  520. //
  521. if (configuration->PortListCount == 0) {
  522. //
  523. // No port configuration information was found, so use
  524. // the driver defaults.
  525. //
  526. InpPrint((
  527. 1,
  528. "INPORT-InpConfigureDevice: Using default port config\n"
  529. ));
  530. configuration->PortList[0].Type = CmResourceTypePort;
  531. configuration->PortList[0].Flags = INPORT_PORT_TYPE;
  532. configuration->PortList[0].Flags = CM_RESOURCE_PORT_IO;
  533. configuration->PortList[0].ShareDisposition =
  534. INPORT_REGISTER_SHARE? CmResourceShareShared:
  535. CmResourceShareDeviceExclusive;
  536. configuration->PortList[0].u.Port.Start.LowPart =
  537. INPORT_PHYSICAL_BASE;
  538. configuration->PortList[0].u.Port.Start.HighPart = 0;
  539. configuration->PortList[0].u.Port.Length = INPORT_REGISTER_LENGTH;
  540. configuration->PortListCount = 1;
  541. }
  542. #else
  543. if (configuration->PortListCount == 0) {
  544. return STATUS_UNSUCCESSFUL;
  545. }
  546. #endif
  547. #if defined(NEC_98)
  548. configuration->PortList[0].u.Port.Length = 1;
  549. #endif // defined(NEC_98)
  550. for (i = 0; i < configuration->PortListCount; i++) {
  551. InpPrint((
  552. 1,
  553. " %s, Ports 0x%x - 0x%x\n",
  554. configuration->PortList[i].ShareDisposition
  555. == CmResourceShareShared? "Sharable" : "NonSharable",
  556. configuration->PortList[i].u.Port.Start.LowPart,
  557. configuration->PortList[i].u.Port.Start.LowPart +
  558. configuration->PortList[i].u.Port.Length - 1
  559. ));
  560. }
  561. //
  562. // Set the DeviceRegister, mapping them if necessary
  563. //
  564. if (DeviceExtension->Configuration.DeviceRegisters[0] == NULL) {
  565. if (DeviceExtension->Configuration.UnmapRegistersRequired) {
  566. InpPrint((1, "INPORT-InpConfigureDevice:Mapping registers\n"));
  567. InpPrint((
  568. 1,
  569. "INPORT-InpConfigureDevice: Start = 0x%x, Length = 0x%x\n",
  570. DeviceExtension->Configuration.PortList[0].u.Port.Start,
  571. DeviceExtension->Configuration.PortList[0].u.Port.Length
  572. ));
  573. DeviceExtension->Configuration.DeviceRegisters[0] = (PUCHAR)
  574. MmMapIoSpace(
  575. DeviceExtension->Configuration.PortList[0].u.Port.Start,
  576. DeviceExtension->Configuration.PortList[0].u.Port.Length,
  577. MmNonCached
  578. );
  579. } else {
  580. InpPrint((1, "INPORT-InpConfigureDevice:Not Mapping registers\n"));
  581. DeviceExtension->Configuration.DeviceRegisters[0] = (PUCHAR)
  582. DeviceExtension->Configuration.PortList[0].u.Port.Start.LowPart;
  583. }
  584. }
  585. return STATUS_SUCCESS;
  586. }
  587. NTSTATUS
  588. InpStartDevice(
  589. IN OUT PDEVICE_EXTENSION DeviceExtension,
  590. IN PCM_RESOURCE_LIST ResourceList
  591. )
  592. {
  593. PINPORT_CONFIGURATION_INFORMATION configuration;
  594. NTSTATUS status;
  595. ULONG dumpData[1],
  596. dumpCount,
  597. uniqueErrorValue,
  598. errorCode;
  599. InpPrint((2, "INPORT-InpStartDevice: enter\n"));
  600. InpServiceParameters(DeviceExtension,
  601. &Globals.RegistryPath);
  602. status = InpConfigureDevice(DeviceExtension,
  603. ResourceList);
  604. if (!NT_SUCCESS(status)) {
  605. return status;
  606. }
  607. status = InpInitializeHardware(DeviceExtension->Self);
  608. if (!NT_SUCCESS(status)) {
  609. return status;
  610. }
  611. //
  612. // Allocate the ring buffer for the mouse input data.
  613. //
  614. DeviceExtension->InputData =
  615. ExAllocatePool(
  616. NonPagedPool,
  617. DeviceExtension->Configuration.MouseAttributes.InputDataQueueLength
  618. );
  619. if (!DeviceExtension->InputData) {
  620. //
  621. // Could not allocate memory for the mouse data queue.
  622. //
  623. InpPrint((
  624. 1,
  625. "INPORT-InpStartDevice: Could not allocate mouse input data queue\n"
  626. ));
  627. //
  628. // Log an error.
  629. //
  630. dumpData[0] =
  631. DeviceExtension->Configuration.MouseAttributes.InputDataQueueLength;
  632. dumpCount = 1;
  633. InpLogError(
  634. DeviceExtension->Self,
  635. INPORT_NO_BUFFER_ALLOCATED,
  636. INPORT_ERROR_VALUE_BASE + 30,
  637. STATUS_INSUFFICIENT_RESOURCES,
  638. dumpData,
  639. 1
  640. );
  641. }
  642. DeviceExtension->DataEnd =
  643. (PMOUSE_INPUT_DATA) ((PCHAR) (DeviceExtension->InputData)
  644. + DeviceExtension->Configuration.MouseAttributes.InputDataQueueLength);
  645. //
  646. // Zero the mouse input data ring buffer.
  647. //
  648. RtlZeroMemory(
  649. DeviceExtension->InputData,
  650. DeviceExtension->Configuration.MouseAttributes.InputDataQueueLength
  651. );
  652. //
  653. // Initialize the input data queue.
  654. //
  655. InpInitializeDataQueue((PVOID) DeviceExtension);
  656. //
  657. // Initialize the port ISR DPC. The ISR DPC is responsible for
  658. // calling the connected class driver's callback routine to process
  659. // the input data queue.
  660. //
  661. DeviceExtension->DpcInterlockVariable = -1;
  662. KeInitializeSpinLock(&DeviceExtension->SpinLock);
  663. KeInitializeDpc(
  664. &DeviceExtension->IsrDpc,
  665. (PKDEFERRED_ROUTINE) InportIsrDpc,
  666. DeviceExtension->Self
  667. );
  668. KeInitializeDpc(
  669. &DeviceExtension->IsrDpcRetry,
  670. (PKDEFERRED_ROUTINE) InportIsrDpc,
  671. DeviceExtension->Self
  672. );
  673. //
  674. // Initialize the mouse data consumption timer.
  675. //
  676. KeInitializeTimer(&DeviceExtension->DataConsumptionTimer);
  677. //
  678. // Initialize the port DPC queue to log overrun and internal
  679. // driver errors.
  680. //
  681. KeInitializeDpc(
  682. &DeviceExtension->ErrorLogDpc,
  683. (PKDEFERRED_ROUTINE) InportErrorLogDpc,
  684. DeviceExtension->Self
  685. );
  686. configuration = &DeviceExtension->Configuration;
  687. //
  688. // Initialize and connect the interrupt object for the mouse.
  689. //
  690. status = IoConnectInterrupt(
  691. &(DeviceExtension->InterruptObject),
  692. (PKSERVICE_ROUTINE) InportInterruptService,
  693. (PVOID) DeviceExtension->Self,
  694. (PKSPIN_LOCK) NULL,
  695. configuration->MouseInterrupt.u.Interrupt.Vector,
  696. (KIRQL) configuration->MouseInterrupt.u.Interrupt.Level,
  697. (KIRQL) configuration->MouseInterrupt.u.Interrupt.Level,
  698. configuration->MouseInterrupt.Flags
  699. == CM_RESOURCE_INTERRUPT_LATCHED ? Latched:LevelSensitive,
  700. (BOOLEAN) (configuration->MouseInterrupt.ShareDisposition
  701. == CmResourceShareShared),
  702. configuration->MouseInterrupt.u.Interrupt.Affinity,
  703. configuration->FloatingSave
  704. );
  705. InpPrint((2, "INPORT-InpStartDevice: exit (%x)\n", status));
  706. return status;
  707. }
  708. VOID
  709. InpDisableInterrupts(
  710. IN PVOID Context
  711. )
  712. /*++
  713. Routine Description:
  714. This routine is called from StartIo synchronously. It touches the
  715. hardware to disable interrupts.
  716. Arguments:
  717. Context - Pointer to the device extension.
  718. Return Value:
  719. None.
  720. --*/
  721. {
  722. PUCHAR port;
  723. PLONG enableCount;
  724. UCHAR mode;
  725. InpPrint((2, "INPORT-InpDisableInterrupts: enter\n"));
  726. //
  727. // Decrement the reference count for device enables.
  728. //
  729. enableCount = &((PDEVICE_EXTENSION) Context)->MouseEnableCount;
  730. *enableCount = *enableCount - 1;
  731. if (*enableCount == 0) {
  732. //
  733. // Get the port register address.
  734. //
  735. port = ((PDEVICE_EXTENSION) Context)->Configuration.DeviceRegisters[0];
  736. #if defined(NEC_98)
  737. //
  738. // Mouse Timer Intrrupt Enable
  739. //
  740. WRITE_PORT_UCHAR(port + PC98_WritePortC2, (UCHAR)PC98_TimerIntDisable);
  741. #else // defined(NEC_98)
  742. //
  743. // Select the mode register as the current data register.
  744. //
  745. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
  746. //
  747. // Read the current mode.
  748. //
  749. mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
  750. //
  751. // Rewrite the mode byte with the interrupt disabled.
  752. //
  753. WRITE_PORT_UCHAR(
  754. (PUCHAR) (port + INPORT_DATA_REGISTER_1),
  755. (UCHAR) (mode & ~INPORT_DATA_INTERRUPT_ENABLE)
  756. );
  757. #endif // defined(NEC_98)
  758. }
  759. InpPrint((2, "INPORT-InpDisableInterrupts: exit\n"));
  760. }
  761. VOID
  762. InpEnableInterrupts(
  763. IN PVOID Context
  764. )
  765. /*++
  766. Routine Description:
  767. This routine is called from StartIo synchronously. It touches the
  768. hardware to enable interrupts.
  769. Arguments:
  770. Context - Pointer to the device extension.
  771. Return Value:
  772. None.
  773. --*/
  774. {
  775. PUCHAR port;
  776. PLONG enableCount;
  777. UCHAR mode;
  778. #if defined(NEC_98)
  779. UCHAR HzMode;
  780. #endif // defined(NEC_98)
  781. InpPrint((2, "INPORT-InpEnableInterrupts: enter\n"));
  782. enableCount = &((PDEVICE_EXTENSION) Context)->MouseEnableCount;
  783. if (*enableCount == 0) {
  784. //
  785. // Get the port register address.
  786. //
  787. port = ((PDEVICE_EXTENSION) Context)->Configuration.DeviceRegisters[0];
  788. #if defined(NEC_98)
  789. //
  790. // Switch to event interrupt mode.
  791. //
  792. if (EventStatus) {
  793. _asm { cli }
  794. WRITE_PORT_UCHAR((PUCHAR)PC98_ConfigurationPort, PC98_EventIntPort);
  795. WRITE_PORT_UCHAR((PUCHAR)PC98_ConfigurationDataPort, PC98_EventIntMode);
  796. _asm { sti }
  797. }
  798. //
  799. // Reset the Inport chip, leaving interrupts off.
  800. //
  801. WRITE_PORT_UCHAR(port + PC98_WriteModePort, PC98_InitializeCommand);
  802. //
  803. // Select the mode register as the current data register.
  804. // Set the Inport mouse up for quadrature mode,
  805. // and set the sample rate (i.e., the interrupt Hz rate).
  806. // Leave interrupts disabled.
  807. //
  808. if (EventStatus) {
  809. HzMode = (((PDEVICE_EXTENSION) Context)->Configuration.HzMode == 0)?
  810. (UCHAR)PC98_EVENT_MODE_120HZ : (UCHAR)PC98_EVENT_MODE_60HZ;
  811. } else {
  812. HzMode = ((PDEVICE_EXTENSION) Context)->Configuration.HzMode;
  813. }
  814. WRITE_PORT_UCHAR(
  815. (PUCHAR)PC98_WriteTimerPort,
  816. (UCHAR)(HzMode|INPORT_MODE_QUADRATURE)
  817. );
  818. //
  819. // Mouse Timer Intrrupt Enable.
  820. //
  821. WRITE_PORT_UCHAR(port + PC98_WritePortC2, (UCHAR)PC98_TimerIntEnable);
  822. #else // defined(NEC_98)
  823. //
  824. // Select the mode register as the current data register.
  825. //
  826. WRITE_PORT_UCHAR((PUCHAR) port, INPORT_MODE_REGISTER);
  827. //
  828. // Read the current mode.
  829. //
  830. mode = READ_PORT_UCHAR((PUCHAR) (port + INPORT_DATA_REGISTER_1));
  831. //
  832. // Rewrite the mode byte with the interrupt enabled.
  833. //
  834. WRITE_PORT_UCHAR(
  835. (PUCHAR) (port + INPORT_DATA_REGISTER_1),
  836. (UCHAR) (mode | INPORT_DATA_INTERRUPT_ENABLE)
  837. );
  838. #endif // defined(NEC_98)
  839. }
  840. //
  841. // Increment the reference count for device enables.
  842. //
  843. *enableCount = *enableCount + 1;
  844. InpPrint((2, "INPORT-InpEnableInterrupts: exit\n"));
  845. }
  846. NTSTATUS
  847. InpInitializeHardware(
  848. IN PDEVICE_OBJECT DeviceObject
  849. )
  850. /*++
  851. Routine Description:
  852. This routine initializes the Inport mouse. Note that this routine is
  853. only called at initialization time, so synchronization is not required.
  854. Arguments:
  855. DeviceObject - Pointer to the device object.
  856. Return Value:
  857. None.
  858. --*/
  859. {
  860. PDEVICE_EXTENSION deviceExtension;
  861. PUCHAR mousePort;
  862. NTSTATUS status = STATUS_SUCCESS;
  863. InpPrint((2, "INPORT-InpInitializeHardware: enter\n"));
  864. //
  865. // Grab useful configuration parameters from the device extension.
  866. //
  867. deviceExtension = DeviceObject->DeviceExtension;
  868. mousePort = deviceExtension->Configuration.DeviceRegisters[0];
  869. #if defined(NEC_98)
  870. //
  871. // Interrupt Disable NEC mouse chip,
  872. // because mouse interrupt Enable at ROM bios started.
  873. //
  874. WRITE_PORT_UCHAR(mousePort + PC98_WriteModePort, PC98_MouseDisable);
  875. #else // defined(NEC_98)
  876. //
  877. // Reset the Inport chip, leaving interrupts off.
  878. //
  879. WRITE_PORT_UCHAR((PUCHAR) mousePort, INPORT_RESET);
  880. //
  881. // Select the mode register as the current data register. Set the
  882. // Inport mouse up for quadrature mode, and set the sample
  883. // rate (i.e., the interrupt Hz rate). Leave interrupts disabled.
  884. //
  885. WRITE_PORT_UCHAR((PUCHAR) mousePort, INPORT_MODE_REGISTER);
  886. WRITE_PORT_UCHAR(
  887. (PUCHAR) ((ULONG)mousePort + INPORT_DATA_REGISTER_1),
  888. (UCHAR) (deviceExtension->Configuration.HzMode
  889. | INPORT_MODE_QUADRATURE)
  890. );
  891. #endif // defined(NEC_98)
  892. InpPrint((2, "INPORT-InpInitializeHardware: exit\n"));
  893. return(status);
  894. }
  895. VOID
  896. InpServiceParameters(
  897. IN PDEVICE_EXTENSION DeviceExtension,
  898. IN PUNICODE_STRING RegistryPath
  899. )
  900. /*++
  901. Routine Description:
  902. This routine retrieves this driver's service parameters information
  903. from the registry.
  904. Arguments:
  905. DeviceExtension - Pointer to the device extension.
  906. RegistryPath - Pointer to the null-terminated Unicode name of the
  907. registry path for this driver.
  908. DeviceName - Pointer to the Unicode string that will receive
  909. the port device name.
  910. Return Value:
  911. None. As a side-effect, sets fields in DeviceExtension->Configuration.
  912. --*/
  913. {
  914. PINPORT_CONFIGURATION_INFORMATION configuration;
  915. PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
  916. UNICODE_STRING parametersPath;
  917. HANDLE keyHandle;
  918. ULONG defaultDataQueueSize = DATA_QUEUE_SIZE;
  919. ULONG numberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
  920. USHORT defaultNumberOfButtons = MOUSE_NUMBER_OF_BUTTONS;
  921. #if defined(NEC_98)
  922. ULONG sampleRate = PC98_MOUSE_SAMPLE_RATE_120HZ;
  923. USHORT defaultSampleRate = PC98_MOUSE_SAMPLE_RATE_120HZ;
  924. ULONG hzMode = PC98_MODE_120HZ;
  925. USHORT defaultHzMode = PC98_MODE_120HZ;
  926. #else // defined(NEC_98)
  927. ULONG sampleRate = MOUSE_SAMPLE_RATE_50HZ;
  928. USHORT defaultSampleRate = MOUSE_SAMPLE_RATE_50HZ;
  929. ULONG hzMode = INPORT_MODE_50HZ;
  930. USHORT defaultHzMode = INPORT_MODE_50HZ;
  931. #endif // defined(NEC_98)
  932. UNICODE_STRING defaultUnicodeName;
  933. NTSTATUS status = STATUS_SUCCESS;
  934. PWSTR path = NULL;
  935. USHORT queriesPlusOne = 6;
  936. #if !defined(NEC_98)
  937. ULONG defaultInterrupt = INP_DEF_VECTOR, interruptOverride;
  938. #endif
  939. configuration = &DeviceExtension->Configuration;
  940. parametersPath.Buffer = NULL;
  941. //
  942. // Registry path is already null-terminated, so just use it.
  943. //
  944. path = RegistryPath->Buffer;
  945. if (NT_SUCCESS(status)) {
  946. //
  947. // Allocate the Rtl query table.
  948. //
  949. parameters = ExAllocatePool(
  950. PagedPool,
  951. sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
  952. );
  953. if (!parameters) {
  954. InpPrint((
  955. 1,
  956. "INPORT-InpServiceParameters: Couldn't allocate table for Rtl query to parameters for %ws\n",
  957. path
  958. ));
  959. status = STATUS_UNSUCCESSFUL;
  960. } else {
  961. RtlZeroMemory(
  962. parameters,
  963. sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
  964. );
  965. //
  966. // Form a path to this driver's Parameters subkey.
  967. //
  968. RtlInitUnicodeString(
  969. &parametersPath,
  970. NULL
  971. );
  972. parametersPath.MaximumLength = RegistryPath->Length +
  973. sizeof(L"\\Parameters");
  974. parametersPath.Buffer = ExAllocatePool(
  975. PagedPool,
  976. parametersPath.MaximumLength
  977. );
  978. if (!parametersPath.Buffer) {
  979. InpPrint((
  980. 1,
  981. "INPORT-InpServiceParameters: Couldn't allocate string for path to parameters for %ws\n",
  982. path
  983. ));
  984. status = STATUS_UNSUCCESSFUL;
  985. }
  986. }
  987. }
  988. if (NT_SUCCESS(status)) {
  989. //
  990. // Form the parameters path.
  991. //
  992. RtlZeroMemory(
  993. parametersPath.Buffer,
  994. parametersPath.MaximumLength
  995. );
  996. RtlAppendUnicodeToString(
  997. &parametersPath,
  998. path
  999. );
  1000. RtlAppendUnicodeToString(
  1001. &parametersPath,
  1002. L"\\Parameters"
  1003. );
  1004. InpPrint((
  1005. 1,
  1006. "INPORT-InpServiceParameters: parameters path is %ws\n",
  1007. parametersPath.Buffer
  1008. ));
  1009. //
  1010. // Form the default pointer port device name, in case it is not
  1011. // specified in the registry.
  1012. //
  1013. RtlInitUnicodeString(
  1014. &defaultUnicodeName,
  1015. DD_POINTER_PORT_BASE_NAME_U
  1016. );
  1017. //
  1018. // Gather all of the "user specified" information from
  1019. // the registry.
  1020. //
  1021. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1022. parameters[0].Name = L"MouseDataQueueSize";
  1023. parameters[0].EntryContext =
  1024. &configuration->MouseAttributes.InputDataQueueLength;
  1025. parameters[0].DefaultType = REG_DWORD;
  1026. parameters[0].DefaultData = &defaultDataQueueSize;
  1027. parameters[0].DefaultLength = sizeof(ULONG);
  1028. parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1029. parameters[1].Name = L"NumberOfButtons";
  1030. parameters[1].EntryContext = &numberOfButtons;
  1031. parameters[1].DefaultType = REG_DWORD;
  1032. parameters[1].DefaultData = &defaultNumberOfButtons;
  1033. parameters[1].DefaultLength = sizeof(USHORT);
  1034. parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1035. parameters[2].Name = L"SampleRate";
  1036. parameters[2].EntryContext = &sampleRate;
  1037. parameters[2].DefaultType = REG_DWORD;
  1038. parameters[2].DefaultData = &defaultSampleRate;
  1039. parameters[2].DefaultLength = sizeof(USHORT);
  1040. parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1041. parameters[3].Name = L"HzMode";
  1042. parameters[3].EntryContext = &hzMode;
  1043. parameters[3].DefaultType = REG_DWORD;
  1044. parameters[3].DefaultData = &defaultHzMode;
  1045. parameters[3].DefaultLength = sizeof(USHORT);
  1046. #if 0
  1047. parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1048. parameters[4].Name = L"PointerDeviceBaseName";
  1049. parameters[4].EntryContext = DeviceName;
  1050. parameters[4].DefaultType = REG_SZ;
  1051. parameters[4].DefaultData = defaultUnicodeName.Buffer;
  1052. parameters[4].DefaultLength = 0;
  1053. #endif
  1054. #if !defined(NEC_98)
  1055. parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1056. parameters[4].Name = L"InterruptOverride";
  1057. parameters[4].EntryContext = &configuration->MouseInterrupt.u.Interrupt.Level;
  1058. parameters[4].DefaultType = REG_DWORD;
  1059. parameters[4].DefaultData = &defaultInterrupt;
  1060. parameters[4].DefaultLength = sizeof(ULONG);
  1061. #endif
  1062. status = RtlQueryRegistryValues(
  1063. RTL_REGISTRY_ABSOLUTE,
  1064. parametersPath.Buffer,
  1065. parameters,
  1066. NULL,
  1067. NULL
  1068. );
  1069. if (!NT_SUCCESS(status)) {
  1070. InpPrint((
  1071. 1,
  1072. "INPORT-InpServiceParameters: RtlQueryRegistryValues failed with 0x%x\n",
  1073. status
  1074. ));
  1075. }
  1076. }
  1077. if (!NT_SUCCESS(status)) {
  1078. //
  1079. // Go ahead and assign driver defaults.
  1080. //
  1081. configuration->MouseAttributes.InputDataQueueLength =
  1082. defaultDataQueueSize;
  1083. // RtlCopyUnicodeString(DeviceName, &defaultUnicodeName);
  1084. }
  1085. //
  1086. // Gather all of the "user specified" information from
  1087. // the registry (this time from the devnode)
  1088. //
  1089. status = IoOpenDeviceRegistryKey(DeviceExtension->PDO,
  1090. PLUGPLAY_REGKEY_DEVICE,
  1091. STANDARD_RIGHTS_READ,
  1092. &keyHandle
  1093. );
  1094. if (NT_SUCCESS(status)) {
  1095. //
  1096. // If the value is not present in devnode, then the default is the value
  1097. // read in from the Services\inport\Parameters key
  1098. //
  1099. ULONG prevDataQueueSize,
  1100. prevNumberOfButtons,
  1101. prevSampleRate,
  1102. prevHzMode;
  1103. #if 0
  1104. UNICODE_STRING prevUnicodeName;
  1105. #endif
  1106. prevDataQueueSize =
  1107. configuration->MouseAttributes.InputDataQueueLength;
  1108. prevNumberOfButtons = numberOfButtons;
  1109. prevSampleRate = sampleRate;
  1110. prevHzMode = hzMode;
  1111. #if 0
  1112. RtlCopyUnicodeString(prevUnicodeName, DeviceName);
  1113. #endif
  1114. parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1115. parameters[0].Name = L"MouseDataQueueSize";
  1116. parameters[0].EntryContext =
  1117. &configuration->MouseAttributes.InputDataQueueLength;
  1118. parameters[0].DefaultType = REG_DWORD;
  1119. parameters[0].DefaultData = &prevDataQueueSize;
  1120. parameters[0].DefaultLength = sizeof(ULONG);
  1121. parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1122. parameters[1].Name = L"NumberOfButtons";
  1123. parameters[1].EntryContext = &numberOfButtons;
  1124. parameters[1].DefaultType = REG_DWORD;
  1125. parameters[1].DefaultData = &prevNumberOfButtons;
  1126. parameters[1].DefaultLength = sizeof(USHORT);
  1127. parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1128. parameters[2].Name = L"SampleRate";
  1129. parameters[2].EntryContext = &sampleRate;
  1130. parameters[2].DefaultType = REG_DWORD;
  1131. parameters[2].DefaultData = &prevSampleRate;
  1132. parameters[2].DefaultLength = sizeof(USHORT);
  1133. parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1134. parameters[3].Name = L"HzMode";
  1135. parameters[3].EntryContext = &hzMode;
  1136. parameters[3].DefaultType = REG_DWORD;
  1137. parameters[3].DefaultData = &prevHzMode;
  1138. parameters[3].DefaultLength = sizeof(USHORT);
  1139. #if 0
  1140. parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1141. parameters[4].Name = L"PointerDeviceBaseName";
  1142. parameters[4].EntryContext = DeviceName;
  1143. parameters[4].DefaultType = REG_SZ;
  1144. parameters[4].DefaultData = prevUnicodeName.Buffer;
  1145. parameters[4].DefaultLength = 0;
  1146. #endif
  1147. #if !defined(NEC_98)
  1148. parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
  1149. parameters[4].Name = L"InterruptOverride";
  1150. parameters[4].EntryContext = &configuration->MouseInterrupt.u.Interrupt.Level;
  1151. parameters[4].DefaultType = REG_DWORD;
  1152. parameters[4].DefaultData = &defaultInterrupt;
  1153. parameters[4].DefaultLength = sizeof(ULONG);
  1154. #endif
  1155. status = RtlQueryRegistryValues(
  1156. RTL_REGISTRY_HANDLE,
  1157. (PWSTR) keyHandle,
  1158. parameters,
  1159. NULL,
  1160. NULL
  1161. );
  1162. if (!NT_SUCCESS(status)) {
  1163. InpPrint((
  1164. 1,
  1165. "INPORT-InpServiceParameters: RtlQueryRegistryValues (via handle) failed (0x%x)\n",
  1166. status
  1167. ));
  1168. }
  1169. ZwClose(keyHandle);
  1170. }
  1171. else {
  1172. InpPrint((
  1173. 1,
  1174. "INPORT-InpServiceParameters: opening devnode handle failed (0x%x)\n",
  1175. status
  1176. ));
  1177. }
  1178. #if 0
  1179. InpPrint((
  1180. 1,
  1181. "INPORT-InpServiceParameters: Pointer port base name = %ws\n",
  1182. DeviceName->Buffer
  1183. ));
  1184. #endif 0
  1185. if (configuration->MouseAttributes.InputDataQueueLength == 0) {
  1186. InpPrint((
  1187. 1,
  1188. "INPORT-InpServiceParameters: overriding MouseInputDataQueueLength = 0x%x\n",
  1189. configuration->MouseAttributes.InputDataQueueLength
  1190. ));
  1191. configuration->MouseAttributes.InputDataQueueLength =
  1192. defaultDataQueueSize;
  1193. }
  1194. configuration->MouseAttributes.InputDataQueueLength *=
  1195. sizeof(MOUSE_INPUT_DATA);
  1196. InpPrint((
  1197. 1,
  1198. "INPORT-InpServiceParameters: MouseInputDataQueueLength = 0x%x\n",
  1199. configuration->MouseAttributes.InputDataQueueLength
  1200. ));
  1201. configuration->MouseAttributes.NumberOfButtons = (USHORT) numberOfButtons;
  1202. InpPrint((
  1203. 1,
  1204. "INPORT-InpServiceParameters: NumberOfButtons = %d\n",
  1205. configuration->MouseAttributes.NumberOfButtons
  1206. ));
  1207. configuration->MouseAttributes.SampleRate = (USHORT) sampleRate;
  1208. InpPrint((
  1209. 1,
  1210. "INPORT-InpServiceParameters: SampleRate = %d\n",
  1211. configuration->MouseAttributes.SampleRate
  1212. ));
  1213. configuration->HzMode = (UCHAR) hzMode;
  1214. InpPrint((
  1215. 1,
  1216. "INPORT-InpServiceParameters: HzMode = %d\n",
  1217. configuration->HzMode
  1218. ));
  1219. //
  1220. // Free the allocated memory before returning.
  1221. //
  1222. if (parametersPath.Buffer)
  1223. ExFreePool(parametersPath.Buffer);
  1224. if (parameters)
  1225. ExFreePool(parameters);
  1226. }
  1227. #if defined(NEC_98)
  1228. #define ISA_BUS_NODE "\\Registry\\MACHINE\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter\\%d"
  1229. ULONG
  1230. QueryEventMode(
  1231. IN OUT VOID
  1232. )
  1233. {
  1234. ULONG NodeNumber = 0;
  1235. NTSTATUS Status;
  1236. RTL_QUERY_REGISTRY_TABLE parameters[2];
  1237. UNICODE_STRING invalidBusName;
  1238. UNICODE_STRING targetBusName;
  1239. UNICODE_STRING isaBusName;
  1240. UCHAR Configuration_Data1[1192];
  1241. ULONG Configuration;
  1242. RTL_QUERY_REGISTRY_TABLE QueryTable[] =
  1243. {
  1244. {NULL,
  1245. RTL_QUERY_REGISTRY_DIRECT,
  1246. L"Configuration Data",
  1247. Configuration_Data1,
  1248. REG_DWORD,
  1249. (PVOID) &Configuration,
  1250. 0},
  1251. {NULL, 0, NULL, NULL, REG_NONE, NULL, 0}
  1252. };
  1253. InpPrint((2,"INPORT-QueryEventMode: enter\n"));
  1254. //
  1255. // Initialize invalid bus name.
  1256. //
  1257. RtlInitUnicodeString(&invalidBusName,L"BADBUS");
  1258. //
  1259. // Initialize "ISA" bus name.
  1260. //
  1261. RtlInitUnicodeString(&isaBusName,L"ISA");
  1262. parameters[0].QueryRoutine = NULL;
  1263. parameters[0].Flags = RTL_QUERY_REGISTRY_REQUIRED |
  1264. RTL_QUERY_REGISTRY_DIRECT;
  1265. parameters[0].Name = L"Identifier";
  1266. parameters[0].EntryContext = &targetBusName;
  1267. parameters[0].DefaultType = REG_SZ;
  1268. parameters[0].DefaultData = &invalidBusName;
  1269. parameters[0].DefaultLength = 0;
  1270. parameters[1].QueryRoutine = NULL;
  1271. parameters[1].Flags = 0;
  1272. parameters[1].Name = NULL;
  1273. parameters[1].EntryContext = NULL;
  1274. do {
  1275. CHAR AnsiBuffer[512];
  1276. ANSI_STRING AnsiString;
  1277. UNICODE_STRING registryPath;
  1278. //
  1279. // Initialize receive buffer.
  1280. //
  1281. targetBusName.Buffer = NULL;
  1282. //
  1283. // Build path buffer...
  1284. //
  1285. sprintf(AnsiBuffer,ISA_BUS_NODE,NodeNumber);
  1286. RtlInitAnsiString(&AnsiString,AnsiBuffer);
  1287. Status = RtlAnsiStringToUnicodeString(&registryPath,&AnsiString,TRUE);
  1288. if (!NT_SUCCESS(Status)) {
  1289. //
  1290. // Cannot get memory for registry path(query fails)
  1291. //
  1292. InpPrint((1,"INPORT-QueryEventMode: cannot get registryPath\n"));
  1293. break;
  1294. }
  1295. //
  1296. // Query it.
  1297. //
  1298. Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
  1299. registryPath.Buffer,
  1300. parameters,
  1301. NULL,
  1302. NULL);
  1303. if (!NT_SUCCESS(Status) || (targetBusName.Buffer == NULL)) {
  1304. RtlFreeUnicodeString(&registryPath);
  1305. break;
  1306. }
  1307. //
  1308. // Is this "ISA" node ?
  1309. //
  1310. if (RtlCompareUnicodeString(&targetBusName,&isaBusName,TRUE) == 0) {
  1311. //
  1312. // Found.
  1313. //
  1314. ((PULONG)Configuration_Data1)[0] = 1192;
  1315. RtlQueryRegistryValues(
  1316. RTL_REGISTRY_ABSOLUTE,
  1317. registryPath.Buffer,
  1318. QueryTable,
  1319. NULL,
  1320. NULL);
  1321. RtlFreeUnicodeString(&registryPath);
  1322. if ((((PCONFIGURATION_DATA) Configuration_Data1)->COM_ID[0] == 0x98) &&
  1323. (((PCONFIGURATION_DATA) Configuration_Data1)->COM_ID[1] == 0x21)) {
  1324. EventStatus = ((PCONFIGURATION_DATA)Configuration_Data1)->EventMouseID.EventMouse;
  1325. }
  1326. break;
  1327. }
  1328. //
  1329. // Can we find any node for this ??
  1330. //
  1331. if (RtlCompareUnicodeString(&targetBusName,&invalidBusName,TRUE) == 0) {
  1332. //
  1333. // Not found.
  1334. //
  1335. InpPrint((1, "INPORT-QueryEventMode: ISA not found"));
  1336. RtlFreeUnicodeString(&registryPath);
  1337. break;
  1338. }
  1339. RtlFreeUnicodeString(&targetBusName);
  1340. //
  1341. // Next node number..
  1342. //
  1343. NodeNumber++;
  1344. } while (TRUE);
  1345. if (targetBusName.Buffer) {
  1346. RtlFreeUnicodeString(&targetBusName);
  1347. }
  1348. InpPrint((2, "INPORT-QueryEventMode: Event Interrupt mode is "));
  1349. if (EventStatus) {
  1350. InpPrint((2, "available\n"));
  1351. } else {
  1352. InpPrint((2, "not available\n"));
  1353. }
  1354. InpPrint((2,"INPORT-QueryEventMode: exit\n"));
  1355. return EventStatus;
  1356. }
  1357. VOID
  1358. InportReinitializeHardware (
  1359. PWORK_QUEUE_ITEM Item
  1360. )
  1361. {
  1362. NTSTATUS status = STATUS_SUCCESS;
  1363. PDEVICE_OBJECT DeviceObject;
  1364. PDEVICE_EXTENSION DeviceExtension;
  1365. PUCHAR port;
  1366. UCHAR HzMode;
  1367. DeviceObject = Globals.DeviceObject;
  1368. InpPrint((2,"INPORT-InportReinitializeHardware: enter\n"));
  1369. status = InpInitializeHardware(DeviceObject);
  1370. if (NT_SUCCESS(status)) {
  1371. DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  1372. InpEnableInterrupts(DeviceExtension);
  1373. //
  1374. // Enable interrupt of hibernation/sleep for NEC_98.
  1375. //
  1376. //
  1377. // Get the port register address.
  1378. //
  1379. port = DeviceExtension->Configuration.DeviceRegisters[0];
  1380. //
  1381. // Switch to event interrupt mode.
  1382. //
  1383. if (EventStatus) {
  1384. _asm { cli }
  1385. WRITE_PORT_UCHAR((PUCHAR)PC98_ConfigurationPort, PC98_EventIntPort);
  1386. WRITE_PORT_UCHAR((PUCHAR)PC98_ConfigurationDataPort, PC98_EventIntMode);
  1387. _asm { sti }
  1388. }
  1389. //
  1390. // Reset the Inport chip, leaving interrupts off.
  1391. //
  1392. WRITE_PORT_UCHAR(port + PC98_WriteModePort, PC98_InitializeCommand);
  1393. //
  1394. // Select the mode register as the current data register.
  1395. // Set the Inport mouse up for quadrature mode,
  1396. // and set the sample rate (i.e., the interrupt Hz rate).
  1397. // Leave interrupts disabled.
  1398. //
  1399. if (EventStatus) {
  1400. HzMode = (DeviceExtension->Configuration.HzMode == 0)?
  1401. (UCHAR)PC98_EVENT_MODE_120HZ : (UCHAR)PC98_EVENT_MODE_60HZ;
  1402. } else {
  1403. HzMode = (UCHAR)(DeviceExtension->Configuration.HzMode|INPORT_MODE_QUADRATURE);
  1404. }
  1405. WRITE_PORT_UCHAR(
  1406. (PUCHAR)PC98_WriteTimerPort,
  1407. (UCHAR)(HzMode|INPORT_MODE_QUADRATURE)
  1408. );
  1409. //
  1410. // Mouse Timer Intrrupt Enable.
  1411. //
  1412. WRITE_PORT_UCHAR(port + PC98_WritePortC2, (UCHAR)PC98_TimerIntEnable);
  1413. }
  1414. else {
  1415. InpPrint((1,"INPORT-InportReinitializeHardware: failed, 0x%x\n", status));
  1416. }
  1417. ExFreePool(Item);
  1418. InpPrint((2,"INPORT-InportReinitializeHardware: exit\n"));
  1419. }
  1420. #endif // defined(NEC_98)
  1421. #endif