VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/i8042prt/i8042cmn.c@ 8170

Last change on this file since 8170 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 66.2 KB
Line 
1
2/*++
3
4Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
5
6Module Name:
7
8 i8042cmn.c
9
10Abstract:
11
12 The common portions of the Intel i8042 port driver which
13 apply to both the keyboard and the auxiliary (PS/2 mouse) device.
14
15Environment:
16
17 Kernel mode only.
18
19Notes:
20
21 NOTES: (Future/outstanding issues)
22
23 - Powerfail not implemented.
24
25 - IOCTL_INTERNAL_KEYBOARD_DISCONNECT and IOCTL_INTERNAL_MOUSE_DISCONNECT
26 have not been implemented. They're not needed until the class
27 unload routine is implemented. Right now, we don't want to allow
28 either the keyboard or the mouse class driver to unload.
29
30 - Consolidate duplicate code, where possible and appropriate.
31
32Revision History:
33
34--*/
35
36#include "stdarg.h"
37#include "stdio.h"
38#include "string.h"
39#include "ntddk.h"
40#include "i8042prt.h"
41#include "i8042log.h"
42
43//
44// Declare the global debug flag for this driver.
45//
46
47#if DBG
48ULONG i8042Debug = 0;
49#endif
50
51
52
53VOID
54I8042CompletionDpc(
55 IN PKDPC Dpc,
56 IN PDEVICE_OBJECT DeviceObject,
57 IN PIRP Irp,
58 IN PVOID Context
59
60/*++
61
62Routine Description:
63
64 This routine runs at DISPATCH_LEVEL IRQL to complete requests.
65 It is queued by the ISR routine.
66
67 Note: Currently, only the keyboard ISR queues this routine.
68 Only the keyboard ISR handles both input and output to
69 the device. The mouse is input-only once it is initialized.
70
71Arguments:
72
73 Dpc - Pointer to the DPC object.
74
75 DeviceObject - Pointer to the device object.
76
77 Irp - Not used.
78
79 Context - Indicates type of error to log.
80
81Return Value:
82
83 None.
84
85--*/
86
87 )
88{
89 PDEVICE_EXTENSION deviceExtension;
90 PIO_STACK_LOCATION irpSp;
91
92 UNREFERENCED_PARAMETER(Dpc);
93 UNREFERENCED_PARAMETER(Context);
94
95 I8xPrint((2, "I8042PRT-I8042CompletionDpc: enter\n"));
96
97 //
98 // Get the device extension and current IRP.
99 //
100
101 deviceExtension = DeviceObject->DeviceExtension;
102
103 //
104 // Stop the command timer.
105 //
106
107 KeCancelTimer(&deviceExtension->CommandTimer);
108
109 //
110 // Get the current IRP.
111 //
112
113 Irp = DeviceObject->CurrentIrp;
114 ASSERT(Irp != NULL);
115
116 //
117 // Get a pointer to the current parameters for this request. The
118 // information is contained in the current stack location.
119 //
120
121 irpSp = IoGetCurrentIrpStackLocation(Irp);
122
123 //
124 // We know we're completing an internal device control request. Switch
125 // on IoControlCode.
126 //
127
128 switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {
129
130 //
131 // Complete the keyboard set indicators request.
132 //
133
134 case IOCTL_KEYBOARD_SET_INDICATORS:
135
136 I8xPrint((
137 2,
138 "I8042PRT-I8042CompletionDpc: keyboard set indicators updated\n"
139 ));
140
141 //
142 // Update the current indicators flag in the device extension.
143 //
144
145 deviceExtension->Configuration.KeyboardIndicators =
146 *(PKEYBOARD_INDICATOR_PARAMETERS)
147 Irp->AssociatedIrp.SystemBuffer;
148
149 I8xPrint((
150 2,
151 "I8042PRT-I8042CompletionDpc: new LED flags 0x%x\n",
152 deviceExtension->Configuration.KeyboardIndicators.LedFlags
153 ));
154
155 break;
156
157 //
158 // Complete the keyboard set typematic request.
159 //
160
161 case IOCTL_KEYBOARD_SET_TYPEMATIC:
162
163 I8xPrint((
164 2,
165 "I8042PRT-I8042CompletionDpc: keyboard set typematic updated\n"
166 ));
167
168 //
169 // Update the current typematic rate/delay in the device extension.
170 //
171
172 deviceExtension->Configuration.KeyRepeatCurrent =
173 *(PKEYBOARD_TYPEMATIC_PARAMETERS)
174 Irp->AssociatedIrp.SystemBuffer;
175
176 I8xPrint((
177 2,
178 "I8042PRT-I8042CompletionDpc: new rate/delay 0x%x/%x\n",
179 deviceExtension->Configuration.KeyRepeatCurrent.Rate,
180 deviceExtension->Configuration.KeyRepeatCurrent.Delay
181 ));
182
183 break;
184
185 default:
186
187 I8xPrint((2, "I8042PRT-I8042CompletionDpc: miscellaneous\n"));
188
189 break;
190
191 }
192
193 //
194 // Set the completion status, start the next packet, and complete the
195 // request.
196 //
197
198 Irp->IoStatus.Status = STATUS_SUCCESS;
199 IoStartNextPacket(DeviceObject, FALSE);
200 IoCompleteRequest (Irp, IO_KEYBOARD_INCREMENT);
201
202 I8xPrint((2, "I8042PRT-I8042CompletionDpc: exit\n"));
203}
204
205
206VOID
207I8042ErrorLogDpc(
208 IN PKDPC Dpc,
209 IN PDEVICE_OBJECT DeviceObject,
210 IN PIRP Irp,
211 IN PVOID Context
212 )
213
214/*++
215
216Routine Description:
217
218 This routine runs at DISPATCH_LEVEL IRQL to log errors that are
219 discovered at IRQL > DISPATCH_LEVEL (e.g., in the ISR routine or
220 in a routine that is executed via KeSynchronizeExecution). There
221 is not necessarily a current request associated with this condition.
222
223Arguments:
224
225 Dpc - Pointer to the DPC object.
226
227 DeviceObject - Pointer to the device object.
228
229 Irp - Not used.
230
231 Context - Indicates type of error to log.
232
233Return Value:
234
235 None.
236
237--*/
238
239{
240 PDEVICE_EXTENSION deviceExtension;
241 PIO_ERROR_LOG_PACKET errorLogEntry;
242
243 UNREFERENCED_PARAMETER(Dpc);
244 UNREFERENCED_PARAMETER(Irp);
245
246 I8xPrint((2, "I8042PRT-I8042ErrorLogDpc: enter\n"));
247
248 deviceExtension = DeviceObject->DeviceExtension;
249
250 //
251 // Log an error packet.
252 //
253
254 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
255 DeviceObject,
256 sizeof(IO_ERROR_LOG_PACKET)
257 + (2 * sizeof(ULONG))
258 );
259 if (errorLogEntry != NULL) {
260
261 errorLogEntry->DumpDataSize = 2 * sizeof(ULONG);
262 if ((ULONG) Context == I8042_KBD_BUFFER_OVERFLOW) {
263 errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 310;
264 errorLogEntry->DumpData[0] = sizeof(KEYBOARD_INPUT_DATA);
265 errorLogEntry->DumpData[1] =
266 deviceExtension->Configuration.KeyboardAttributes.InputDataQueueLength;
267 } else if ((ULONG) Context == I8042_MOU_BUFFER_OVERFLOW) {
268 errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 320;
269 errorLogEntry->DumpData[0] = sizeof(MOUSE_INPUT_DATA);
270 errorLogEntry->DumpData[1] =
271 deviceExtension->Configuration.MouseAttributes.InputDataQueueLength;
272 } else {
273 errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 330;
274 errorLogEntry->DumpData[0] = 0;
275 errorLogEntry->DumpData[1] = 0;
276 }
277
278 errorLogEntry->ErrorCode = (ULONG) Context;
279 errorLogEntry->SequenceNumber = 0;
280 errorLogEntry->MajorFunctionCode = 0;
281 errorLogEntry->IoControlCode = 0;
282 errorLogEntry->RetryCount = 0;
283 errorLogEntry->FinalStatus = 0;
284
285 IoWriteErrorLogEntry(errorLogEntry);
286 }
287
288 I8xPrint((2, "I8042PRT-I8042ErrorLogDpc: exit\n"));
289
290}
291
292
293NTSTATUS
294I8042Flush(
295 IN PDEVICE_OBJECT DeviceObject,
296 IN PIRP Irp
297 )
298{
299 UNREFERENCED_PARAMETER(DeviceObject);
300 UNREFERENCED_PARAMETER(Irp);
301
302 I8xPrint((2,"I8042PRT-I8042Flush: enter\n"));
303 I8xPrint((2,"I8042PRT-I8042Flush: exit\n"));
304
305 return(STATUS_NOT_IMPLEMENTED);
306}
307
308
309NTSTATUS
310I8042InternalDeviceControl(
311 IN PDEVICE_OBJECT DeviceObject,
312 IN PIRP Irp
313 )
314
315/*++
316
317Routine Description:
318
319 This routine is the dispatch routine for internal device control requests.
320
321Arguments:
322
323 DeviceObject - Pointer to the device object.
324
325 Irp - Pointer to the request packet.
326
327Return Value:
328
329 Status is returned.
330
331--*/
332
333{
334
335 PIO_STACK_LOCATION irpSp;
336 PDEVICE_EXTENSION deviceExtension;
337 NTSTATUS status;
338 I8042_INITIALIZE_DATA_CONTEXT initializeDataContext;
339 PVOID parameters;
340 PKEYBOARD_ATTRIBUTES keyboardAttributes;
341 ULONG sizeOfTranslation;
342
343 I8xPrint((2,"I8042PRT-I8042InternalDeviceControl: enter\n"));
344
345 //
346 // Get a pointer to the device extension.
347 //
348
349 deviceExtension = DeviceObject->DeviceExtension;
350
351 //
352 // Initialize the returned Information field.
353 //
354
355 Irp->IoStatus.Information = 0;
356
357 //
358 // Get a pointer to the current parameters for this request. The
359 // information is contained in the current stack location.
360 //
361
362 irpSp = IoGetCurrentIrpStackLocation(Irp);
363
364 //
365 // Case on the device control subfunction that is being performed by the
366 // requestor.
367 //
368
369 switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
370
371 //
372 // Connect a keyboard class device driver to the port driver.
373 //
374
375 case IOCTL_INTERNAL_KEYBOARD_CONNECT:
376
377 I8xPrint((
378 2,
379 "I8042PRT-I8042InternalDeviceControl: keyboard connect\n"
380 ));
381
382 //
383 // Only allow a connection if the keyboard hardware is present.
384 // Also, only allow one connection.
385 //
386 // FUTURE: Consider allowing multiple connections, just for
387 // the sake of generality? It really makes no sense for the
388 // i8042, though.
389 //
390
391 if ((deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
392 != KEYBOARD_HARDWARE_PRESENT) {
393
394 I8xPrint((
395 2,
396 "I8042PRT-I8042InternalDeviceControl: error - hardware not present\n"
397 ));
398
399 status = STATUS_NO_SUCH_DEVICE;
400 break;
401 } else
402 if (deviceExtension->KeyboardExtension.ConnectData.ClassService
403 != NULL) {
404
405 I8xPrint((
406 2,
407 "I8042PRT-I8042InternalDeviceControl: error - already connected\n"
408 ));
409
410 status = STATUS_SHARING_VIOLATION;
411 break;
412
413 } else
414 if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
415 sizeof(CONNECT_DATA)) {
416
417 I8xPrint((
418 2,
419 "I8042PRT-I8042InternalDeviceControl: error - invalid buffer length\n"
420 ));
421
422 status = STATUS_INVALID_PARAMETER;
423 break;
424 }
425
426 //
427 // Copy the connection parameters to the device extension.
428 //
429
430 deviceExtension->KeyboardExtension.ConnectData =
431 *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
432
433 //
434 // Reinitialize the port input data queue.
435 //
436
437 initializeDataContext.DeviceExtension = deviceExtension;
438 initializeDataContext.DeviceType = KeyboardDeviceType;
439
440 KeSynchronizeExecution(
441 deviceExtension->KeyboardInterruptObject,
442 (PKSYNCHRONIZE_ROUTINE) I8xInitializeDataQueue,
443 (PVOID) &initializeDataContext
444 );
445
446 //
447 // Set the completion status.
448 //
449
450 status = STATUS_SUCCESS;
451 break;
452
453 //
454 // Disconnect a keyboard class device driver from the port driver.
455 //
456 // NOTE: Not implemented.
457 //
458
459 case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
460
461 I8xPrint((
462 2,
463 "I8042PRT-I8042InternalDeviceControl: keyboard disconnect\n"
464 ));
465
466 //
467 // Perform a keyboard interrupt disable call.
468 //
469
470 //
471 // Clear the connection parameters in the device extension.
472 // NOTE: Must synchronize this with the keyboard ISR.
473 //
474 //
475 //deviceExtension->KeyboardExtension.ConnectData.ClassDeviceObject =
476 // Null;
477 //deviceExtension->KeyboardExtension.ConnectData.ClassService =
478 // Null;
479
480 //
481 // Set the completion status.
482 //
483
484 status = STATUS_NOT_IMPLEMENTED;
485 break;
486
487 //
488 // Connect a mouse class device driver to the port driver.
489 //
490
491 case IOCTL_INTERNAL_MOUSE_CONNECT:
492
493 I8xPrint((
494 2,
495 "I8042PRT-I8042InternalDeviceControl: mouse connect\n"
496 ));
497
498
499 //
500 // Only allow a connection if the mouse hardware is present.
501 // Also, only allow one connection.
502 //
503 // FUTURE: Consider allowing multiple connections, just for
504 // the sake of generality? It really makes no sense for the
505 // i8042, though.
506 //
507
508 if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT)
509 != MOUSE_HARDWARE_PRESENT) {
510
511 I8xPrint((
512 2,
513 "I8042PRT-I8042InternalDeviceControl: error - hardware not present\n"
514 ));
515
516 status = STATUS_NO_SUCH_DEVICE;
517 break;
518 } else
519 if (deviceExtension->MouseExtension.ConnectData.ClassService
520 != NULL) {
521
522 I8xPrint((
523 2,
524 "I8042PRT-I8042InternalDeviceControl: error - already connected\n"
525 ));
526
527 status = STATUS_SHARING_VIOLATION;
528 break;
529
530 } else
531 if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
532 sizeof(CONNECT_DATA)) {
533
534 I8xPrint((
535 2,
536 "I8042PRT-I8042InternalDeviceControl: error - invalid buffer length\n"
537 ));
538
539 status = STATUS_INVALID_PARAMETER;
540 break;
541 }
542
543 //
544 // Copy the connection parameters to the device extension.
545 //
546
547 deviceExtension->MouseExtension.ConnectData =
548 *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
549
550 //
551 // Reinitialize the port input data queue.
552 //
553
554 initializeDataContext.DeviceExtension = deviceExtension;
555 initializeDataContext.DeviceType = MouseDeviceType;
556
557 KeSynchronizeExecution(
558 deviceExtension->MouseInterruptObject,
559 (PKSYNCHRONIZE_ROUTINE) I8xInitializeDataQueue,
560 (PVOID) &initializeDataContext
561 );
562
563 //
564 // Set the completion status.
565 //
566
567 status = STATUS_SUCCESS;
568 break;
569
570 //
571 // Disconnect a mouse class device driver from the port driver.
572 //
573 // NOTE: Not implemented.
574 //
575
576 case IOCTL_INTERNAL_MOUSE_DISCONNECT:
577
578 I8xPrint((
579 2,
580 "I8042PRT-I8042InternalDeviceControl: mouse disconnect\n"
581 ));
582
583 //
584 // Perform a mouse interrupt disable call.
585 //
586
587 //
588 // Clear the connection parameters in the device extension.
589 // NOTE: Must synchronize this with the mouse ISR.
590 //
591 //
592 //deviceExtension->MouseExtension.ConnectData.ClassDeviceObject =
593 // Null;
594 //deviceExtension->MouseExtension.ConnectData.ClassService =
595 // Null;
596
597 //
598 // Set the completion status.
599 //
600
601 status = STATUS_NOT_IMPLEMENTED;
602 break;
603
604 //
605 // Enable keyboard interrupts (mark the request pending and handle
606 // it in StartIo).
607 //
608
609 case IOCTL_INTERNAL_KEYBOARD_ENABLE:
610
611 I8xPrint((
612 2,
613 "I8042PRT-I8042InternalDeviceControl: keyboard enable\n"
614 ));
615
616 status = STATUS_PENDING;
617 break;
618
619 //
620 // Disable keyboard interrupts (mark the request pending and handle
621 // it in StartIo).
622 //
623
624 case IOCTL_INTERNAL_KEYBOARD_DISABLE:
625
626 I8xPrint((
627 2,
628 "I8042PRT-I8042InternalDeviceControl: keyboard disable\n"
629 ));
630
631 status = STATUS_PENDING;
632 break;
633
634 //
635 // Enable mouse interrupts (mark the request pending and handle
636 // it in StartIo).
637 //
638
639 case IOCTL_INTERNAL_MOUSE_ENABLE:
640
641 I8xPrint((
642 2,
643 "I8042PRT-I8042InternalDeviceControl: mouse enable\n"
644 ));
645
646 status = STATUS_PENDING;
647 break;
648
649 //
650 // Disable mouse interrupts (mark the request pending and handle
651 // it in StartIo).
652 //
653
654 case IOCTL_INTERNAL_MOUSE_DISABLE:
655
656 I8xPrint((
657 2,
658 "I8042PRT-I8042InternalDeviceControl: mouse disable\n"
659 ));
660
661 status = STATUS_PENDING;
662 break;
663
664 //
665 // Query the keyboard attributes. First check for adequate buffer
666 // length. Then, copy the keyboard attributes from the device
667 // extension to the output buffer.
668 //
669
670 case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
671
672 I8xPrint((
673 2,
674 "I8042PRT-I8042InternalDeviceControl: keyboard query attributes\n"
675 ));
676
677 if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
678 sizeof(KEYBOARD_ATTRIBUTES)) {
679 status = STATUS_BUFFER_TOO_SMALL;
680 } else {
681
682 //
683 // Copy the attributes from the DeviceExtension to the
684 // buffer.
685 //
686
687 *(PKEYBOARD_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer =
688 deviceExtension->Configuration.KeyboardAttributes;
689
690 Irp->IoStatus.Information = sizeof(KEYBOARD_ATTRIBUTES);
691 status = STATUS_SUCCESS;
692 }
693
694 break;
695
696 //
697 // Query the scan code to indicator-light mapping. Validate the
698 // parameters, and copy the indicator mapping information from
699 // the port device extension to the SystemBuffer.
700 //
701
702 case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
703
704 I8xPrint((
705 2,
706 "I8042PRT-I8042InternalDeviceControl: keyboard query indicator translation\n"
707 ));
708
709 sizeOfTranslation = sizeof(KEYBOARD_INDICATOR_TRANSLATION)
710 + (sizeof(INDICATOR_LIST)
711 * (deviceExtension->Configuration.KeyboardAttributes.NumberOfIndicators - 1));
712
713 if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
714 sizeOfTranslation) {
715 status = STATUS_BUFFER_TOO_SMALL;
716 } else {
717
718 //
719 // Copy the indicator mapping information to the system
720 // buffer.
721 //
722
723 ((PKEYBOARD_INDICATOR_TRANSLATION)
724 Irp->AssociatedIrp.SystemBuffer)->NumberOfIndicatorKeys =
725 deviceExtension->Configuration.KeyboardAttributes.NumberOfIndicators;
726 RtlMoveMemory(
727 ((PKEYBOARD_INDICATOR_TRANSLATION)
728 Irp->AssociatedIrp.SystemBuffer)->IndicatorList,
729 (PCHAR) IndicatorList,
730 sizeOfTranslation
731 );
732
733 Irp->IoStatus.Information = sizeOfTranslation;
734 status = STATUS_SUCCESS;
735 }
736
737 break;
738
739 //
740 // Query the keyboard indicators. Validate the parameters, and
741 // copy the indicator information from the port device extension to
742 // the SystemBuffer.
743 //
744
745 case IOCTL_KEYBOARD_QUERY_INDICATORS:
746
747
748 I8xPrint((
749 2,
750 "I8042PRT-I8042InternalDeviceControl: keyboard query indicators\n"
751 ));
752
753 if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
754 sizeof(KEYBOARD_INDICATOR_PARAMETERS)) {
755 status = STATUS_BUFFER_TOO_SMALL;
756 } else {
757
758 //
759 // Don't bother to synchronize access to the DeviceExtension
760 // KeyboardIndicators field while copying it. We don't
761 // really care if another process is setting the LEDs via
762 // StartIo running on another processor.
763 //
764
765 *(PKEYBOARD_INDICATOR_PARAMETERS)
766 Irp->AssociatedIrp.SystemBuffer =
767 deviceExtension->Configuration.KeyboardIndicators;
768 Irp->IoStatus.Information =
769 sizeof(KEYBOARD_INDICATOR_PARAMETERS);
770 status = STATUS_SUCCESS;
771 }
772
773 break;
774
775 //
776 // Set the keyboard indicators (validate the parameters, mark the
777 // request pending, and handle it in StartIo).
778 //
779
780 case IOCTL_KEYBOARD_SET_INDICATORS:
781
782 I8xPrint((
783 2,
784 "I8042PRT-I8042InternalDeviceControl: keyboard set indicators\n"
785 ));
786
787#ifdef JAPAN
788// Katakana keyboard indicator support
789 if ((irpSp->Parameters.DeviceIoControl.InputBufferLength <
790 sizeof(KEYBOARD_INDICATOR_PARAMETERS)) ||
791 ((((PKEYBOARD_INDICATOR_PARAMETERS)
792 Irp->AssociatedIrp.SystemBuffer)->LedFlags
793 & ~(KEYBOARD_SCROLL_LOCK_ON
794 | KEYBOARD_NUM_LOCK_ON | KEYBOARD_CAPS_LOCK_ON
795 | KEYBOARD_KANA_LOCK_ON)) != 0)) {
796 status = STATUS_INVALID_PARAMETER;
797 } else {
798 PKEYBOARD_ID KeyboardId;
799 KeyboardId = &deviceExtension->Configuration.KeyboardAttributes.KeyboardIdentifier;
800 if (! AX_KEYBOARD(*KeyboardId) &&
801 (((PKEYBOARD_INDICATOR_PARAMETERS)
802 Irp->AssociatedIrp.SystemBuffer)->LedFlags
803 & KEYBOARD_KANA_LOCK_ON)) {
804 ((PKEYBOARD_INDICATOR_PARAMETERS)
805 Irp->AssociatedIrp.SystemBuffer)->LedFlags &=
806 ~(KEYBOARD_KANA_LOCK_ON);
807 }
808 status = STATUS_PENDING;
809 }
810#else
811 if ((irpSp->Parameters.DeviceIoControl.InputBufferLength <
812 sizeof(KEYBOARD_INDICATOR_PARAMETERS)) ||
813 ((((PKEYBOARD_INDICATOR_PARAMETERS)
814 Irp->AssociatedIrp.SystemBuffer)->LedFlags
815 & ~(KEYBOARD_SCROLL_LOCK_ON
816 | KEYBOARD_NUM_LOCK_ON | KEYBOARD_CAPS_LOCK_ON)) != 0)) {
817 status = STATUS_INVALID_PARAMETER;
818 } else {
819 status = STATUS_PENDING;
820 }
821#endif
822
823 break;
824
825 //
826 // Query the current keyboard typematic rate and delay. Validate
827 // the parameters, and copy the typematic information from the port
828 // device extension to the SystemBuffer.
829 //
830
831 case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
832
833 I8xPrint((
834 2,
835 "I8042PRT-I8042InternalDeviceControl: keyboard query typematic\n"
836 ));
837
838 if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
839 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) {
840 status = STATUS_BUFFER_TOO_SMALL;
841 } else {
842
843 //
844 // Don't bother to synchronize access to the DeviceExtension
845 // KeyRepeatCurrent field while copying it. We don't
846 // really care if another process is setting the typematic
847 // rate/delay via StartIo running on another processor.
848 //
849
850 *(PKEYBOARD_TYPEMATIC_PARAMETERS)
851 Irp->AssociatedIrp.SystemBuffer =
852 deviceExtension->Configuration.KeyRepeatCurrent;
853 Irp->IoStatus.Information =
854 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS);
855 status = STATUS_SUCCESS;
856 }
857
858 break;
859
860 //
861 // Set the keyboard typematic rate and delay (validate the parameters,
862 // mark the request pending, and handle it in StartIo).
863 //
864
865 case IOCTL_KEYBOARD_SET_TYPEMATIC:
866
867 I8xPrint((
868 2,
869 "I8042PRT-I8042InternalDeviceControl: keyboard set typematic\n"
870 ));
871
872 parameters = Irp->AssociatedIrp.SystemBuffer;
873 keyboardAttributes =
874 &deviceExtension->Configuration.KeyboardAttributes;
875
876 if ((irpSp->Parameters.DeviceIoControl.InputBufferLength <
877 sizeof(KEYBOARD_TYPEMATIC_PARAMETERS)) ||
878 (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Rate <
879 keyboardAttributes->KeyRepeatMinimum.Rate) ||
880 (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Rate >
881 keyboardAttributes->KeyRepeatMaximum.Rate) ||
882 (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Delay <
883 keyboardAttributes->KeyRepeatMinimum.Delay) ||
884 (((PKEYBOARD_TYPEMATIC_PARAMETERS) parameters)->Delay >
885 keyboardAttributes->KeyRepeatMaximum.Delay)) {
886 status = STATUS_INVALID_PARAMETER;
887 } else {
888 status = STATUS_PENDING;
889 }
890
891 break;
892
893 //
894 // Query the mouse attributes. First check for adequate buffer
895 // length. Then, copy the mouse attributes from the device
896 // extension to the output buffer.
897 //
898
899 case IOCTL_MOUSE_QUERY_ATTRIBUTES:
900
901 I8xPrint((
902 2,
903 "I8042PRT-I8042InternalDeviceControl: mouse query attributes\n"
904 ));
905
906 if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
907 sizeof(MOUSE_ATTRIBUTES)) {
908 status = STATUS_BUFFER_TOO_SMALL;
909 } else {
910
911 //
912 // Copy the attributes from the DeviceExtension to the
913 // buffer.
914 //
915
916 *(PMOUSE_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer =
917 deviceExtension->Configuration.MouseAttributes;
918
919 Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
920 status = STATUS_SUCCESS;
921 }
922
923 break;
924
925 default:
926
927 I8xPrint((
928 2,
929 "I8042PRT-I8042InternalDeviceControl: INVALID REQUEST\n"
930 ));
931
932 status = STATUS_INVALID_DEVICE_REQUEST;
933 break;
934 }
935
936 Irp->IoStatus.Status = status;
937 if (status == STATUS_PENDING) {
938 IoMarkIrpPending(Irp);
939 IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL);
940 } else {
941 IoCompleteRequest(Irp, IO_NO_INCREMENT);
942 }
943
944 I8xPrint((2,"I8042PRT-I8042InternalDeviceControl: exit\n"));
945
946 return(status);
947
948}
949
950
951NTSTATUS
952I8042OpenCloseDispatch(
953 IN PDEVICE_OBJECT DeviceObject,
954 IN PIRP Irp
955 )
956
957/*++
958
959Routine Description:
960
961 This is the dispatch routine for create/open and close requests.
962 These requests complete successfully.
963
964Arguments:
965
966 DeviceObject - Pointer to the device object.
967
968 Irp - Pointer to the request packet.
969
970Return Value:
971
972 Status is returned.
973
974--*/
975
976{
977
978 UNREFERENCED_PARAMETER(DeviceObject);
979
980 dprintf(("I8042PRT-I8042OpenCloseDispatch: enter\n"));
981 I8xPrint((3,"I8042PRT-I8042OpenCloseDispatch: enter\n"));
982
983 //
984 // Complete the request with successful status.
985 //
986
987 Irp->IoStatus.Status = STATUS_SUCCESS;
988 Irp->IoStatus.Information = 0;
989 IoCompleteRequest(Irp, IO_NO_INCREMENT);
990
991 I8xPrint((3,"I8042PRT-I8042OpenCloseDispatch: exit\n"));
992
993 return(STATUS_SUCCESS);
994
995}
996
997
998VOID
999I8042RetriesExceededDpc(
1000 IN PKDPC Dpc,
1001 IN PDEVICE_OBJECT DeviceObject,
1002 IN PIRP Irp,
1003 IN PVOID Context
1004 )
1005
1006/*++
1007
1008Routine Description:
1009
1010 This routine runs at DISPATCH_LEVEL IRQL to complete requests that
1011 have exceeded the maximum number of retries. It is queued in the
1012 keyboard ISR.
1013
1014Arguments:
1015
1016 Dpc - Pointer to the DPC object.
1017
1018 DeviceObject - Pointer to the device object.
1019
1020 Irp - Pointer to the Irp.
1021
1022 Context - Not used.
1023
1024Return Value:
1025
1026 None.
1027
1028--*/
1029
1030{
1031 PDEVICE_EXTENSION deviceExtension;
1032 PIO_ERROR_LOG_PACKET errorLogEntry;
1033 PIO_STACK_LOCATION irpSp;
1034
1035 UNREFERENCED_PARAMETER(Dpc);
1036 UNREFERENCED_PARAMETER(Context);
1037
1038 I8xPrint((2, "I8042PRT-I8042RetriesExceededDpc: enter\n"));
1039
1040 deviceExtension = DeviceObject->DeviceExtension;
1041
1042 //
1043 // Set the completion status.
1044 //
1045
1046 Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
1047
1048 //
1049 // Log an error.
1050 //
1051
1052 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
1053 DeviceObject,
1054 sizeof(IO_ERROR_LOG_PACKET)
1055 + (3 * sizeof(ULONG))
1056 );
1057 if (errorLogEntry != NULL) {
1058
1059 errorLogEntry->ErrorCode = I8042_RETRIES_EXCEEDED;
1060 errorLogEntry->DumpDataSize = 3 * sizeof(ULONG);
1061 errorLogEntry->SequenceNumber =
1062 deviceExtension->KeyboardExtension.SequenceNumber;
1063 irpSp = IoGetCurrentIrpStackLocation(Irp);
1064 errorLogEntry->MajorFunctionCode = irpSp->MajorFunction;
1065 errorLogEntry->IoControlCode =
1066 irpSp->Parameters.DeviceIoControl.IoControlCode;
1067 errorLogEntry->RetryCount = (UCHAR)
1068 deviceExtension->KeyboardExtension.ResendCount;
1069 errorLogEntry->UniqueErrorValue = I8042_ERROR_VALUE_BASE + 210;
1070 errorLogEntry->FinalStatus = Irp->IoStatus.Status;
1071 errorLogEntry->DumpData[0] =
1072 deviceExtension->KeyboardExtension.CurrentOutput.State;
1073 errorLogEntry->DumpData[1] =
1074 deviceExtension->KeyboardExtension.CurrentOutput.FirstByte;
1075 errorLogEntry->DumpData[2] =
1076 deviceExtension->KeyboardExtension.CurrentOutput.LastByte;
1077
1078 IoWriteErrorLogEntry(errorLogEntry);
1079 }
1080
1081 //
1082 // Start the next packet and complete the request.
1083 //
1084
1085 IoStartNextPacket(DeviceObject, FALSE);
1086 IoCompleteRequest (Irp, IO_KEYBOARD_INCREMENT);
1087
1088 I8xPrint((2, "I8042PRT-I8042RetriesExceededDpc: exit\n"));
1089
1090}
1091
1092
1093VOID
1094I8042StartIo(
1095 IN PDEVICE_OBJECT DeviceObject,
1096 IN PIRP Irp
1097 )
1098
1099/*++
1100
1101Routine Description:
1102
1103 This routine starts an I/O operation for the device.
1104
1105Arguments:
1106
1107 DeviceObject - Pointer to the device object.
1108
1109 Irp - Pointer to the request packet.
1110
1111Return Value:
1112
1113 None.
1114
1115--*/
1116
1117{
1118 PDEVICE_EXTENSION deviceExtension;
1119 PIO_STACK_LOCATION irpSp;
1120 KEYBOARD_INITIATE_CONTEXT keyboardInitiateContext;
1121 LARGE_INTEGER deltaTime;
1122 LONG interlockedResult;
1123
1124 dprintf(("I8042PRT-I8042StartIo: enter\n"));
1125 I8xPrint((2, "I8042PRT-I8042StartIo: enter\n"));
1126
1127 deviceExtension = DeviceObject->DeviceExtension;
1128
1129 //
1130 // Bump the error log sequence number.
1131 //
1132
1133 deviceExtension->KeyboardExtension.SequenceNumber += 1;
1134
1135 //
1136 // Get a pointer to the current parameters for this request. The
1137 // information is contained in the current stack location.
1138 //
1139
1140 irpSp = IoGetCurrentIrpStackLocation(Irp);
1141
1142 //
1143 // We know we got here with an internal device control request. Switch
1144 // on IoControlCode.
1145 //
1146
1147 switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {
1148
1149 //
1150 // Enable the keyboard device.
1151 //
1152
1153 case IOCTL_INTERNAL_KEYBOARD_ENABLE:
1154
1155 //
1156 // Enable keyboard by incrementing the KeyboardEnableCount
1157 // field. The keyboard ISR will start processing keyboard
1158 // interrupts when KeyboardEnableCount is non-zero. Note that
1159 // the keyboard device and its interrupts are *always* enabled
1160 // in the i8042 Controller Command Byte, following initialization.
1161 // Interrupts are ignored in the ISR, however, until the
1162 // KeyboardEnableCount is greater than zero (indicating that the
1163 // user has "enabled" the device).
1164 //
1165
1166 interlockedResult = InterlockedIncrement(
1167 &deviceExtension->KeyboardEnableCount
1168 );
1169
1170 I8xPrint((
1171 2,
1172 "I8042PRT-I8042StartIo: keyboard enable (count %d)\n",
1173 deviceExtension->KeyboardEnableCount
1174 ));
1175
1176 Irp->IoStatus.Status = STATUS_SUCCESS;
1177
1178 //
1179 // Complete the request.
1180 //
1181
1182 IoStartNextPacket(DeviceObject, FALSE);
1183 IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
1184
1185 break;
1186
1187 //
1188 // Disable the keyboard device.
1189 //
1190
1191 case IOCTL_INTERNAL_KEYBOARD_DISABLE:
1192
1193 I8xPrint((2, "I8042PRT-I8042StartIo: keyboard disable"));
1194
1195 if (deviceExtension->KeyboardEnableCount == 0) {
1196
1197 //
1198 // Keyboard already disabled.
1199 //
1200
1201 I8xPrint((2, " - error\n"));
1202
1203 Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
1204
1205 } else {
1206
1207 //
1208 // Disable keyboard by decrementing the KeyboardEnableCount
1209 // field. The keyboard ISR will ignore keyboard
1210 // interrupts when KeyboardEnableCount is zero.
1211 //
1212
1213 InterlockedDecrement(
1214 &deviceExtension->KeyboardEnableCount
1215 );
1216
1217 I8xPrint((
1218 2,
1219 " (count %d)\n",
1220 deviceExtension->KeyboardEnableCount
1221 ));
1222
1223 Irp->IoStatus.Status = STATUS_SUCCESS;
1224 }
1225
1226 //
1227 // Complete the request.
1228 //
1229
1230 IoStartNextPacket(DeviceObject, FALSE);
1231 IoCompleteRequest(Irp, IO_KEYBOARD_INCREMENT);
1232
1233 break;
1234
1235 //
1236 // Enable the mouse device.
1237 //
1238
1239 case IOCTL_INTERNAL_MOUSE_ENABLE:
1240
1241 //
1242 // Enable mouse by incrementing the MouseEnableCount
1243 // field. The mouse ISR will start processing mouse
1244 // interrupts when MouseEnableCount is non-zero. Note that
1245 // the mouse device and its interrupts are *always* enabled
1246 // in the i8042 Controller Command Byte, following initialization.
1247 // Interrupts are ignored in the ISR, however, until the
1248 // MouseEnableCount is greater than zero (indicating that the
1249 // user has "enabled" the device).
1250 //
1251
1252
1253 InterlockedIncrement(&deviceExtension->MouseEnableCount);
1254
1255 I8xPrint((
1256 2,
1257 "I8042PRT-I8042StartIo: mouse enable (count %d)\n",
1258 deviceExtension->MouseEnableCount
1259 ));
1260
1261 Irp->IoStatus.Status = STATUS_SUCCESS;
1262
1263 //
1264 // Complete the request.
1265 //
1266
1267 IoStartNextPacket(DeviceObject, FALSE);
1268 IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
1269
1270 break;
1271
1272 //
1273 // Disable the mouse device.
1274 //
1275
1276 case IOCTL_INTERNAL_MOUSE_DISABLE:
1277
1278 I8xPrint((2, "I8042PRT-I8042StartIo: mouse disable"));
1279
1280 if (deviceExtension->MouseEnableCount == 0) {
1281
1282 //
1283 // Mouse already disabled.
1284 //
1285
1286 I8xPrint((2, " - error\n"));
1287
1288 Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
1289
1290 } else {
1291
1292 //
1293 // Disable mouse by decrementing the MouseEnableCount
1294 // field. The mouse ISR will ignore keyboard
1295 // interrupts when MouseEnableCount is zero.
1296 //
1297
1298 InterlockedDecrement(
1299 &deviceExtension->MouseEnableCount
1300 );
1301
1302 I8xPrint((
1303 2,
1304 " (count %d)\n",
1305 deviceExtension->MouseEnableCount
1306 ));
1307
1308 Irp->IoStatus.Status = STATUS_SUCCESS;
1309 }
1310
1311 //
1312 // Complete the request.
1313 //
1314
1315 IoStartNextPacket(DeviceObject, FALSE);
1316 IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
1317
1318 break;
1319
1320 //
1321 // Set the keyboard indicators to the desired state.
1322 //
1323
1324 case IOCTL_KEYBOARD_SET_INDICATORS:
1325
1326 I8xPrint((2, "I8042PRT-I8042StartIo: keyboard set indicators\n"));
1327
1328 //
1329 // Set up the context structure for the InitiateIo wrapper.
1330 //
1331
1332 keyboardInitiateContext.DeviceObject = DeviceObject;
1333 keyboardInitiateContext.FirstByte = SET_KEYBOARD_INDICATORS;
1334 keyboardInitiateContext.LastByte =
1335 (UCHAR) ((PKEYBOARD_INDICATOR_PARAMETERS)
1336 Irp->AssociatedIrp.SystemBuffer)->LedFlags;
1337
1338 //
1339 // Call the InitiateIo wrapper synchronously. The wrapper
1340 // stores the context parameters in the device extension,
1341 // and then initiates the I/O operation, all synchronized
1342 // with the keyboard ISR.
1343 //
1344
1345 KeSynchronizeExecution(
1346 deviceExtension->KeyboardInterruptObject,
1347 (PKSYNCHRONIZE_ROUTINE) I8xKeyboardInitiateWrapper,
1348 (PVOID) &keyboardInitiateContext
1349 );
1350
1351 //
1352 // Start the 1-second command timer. InitiateIo changed
1353 // the TimerCount already.
1354 //
1355
1356 deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
1357 deltaTime.HighPart = -1;
1358
1359 (VOID) KeSetTimer(
1360 &deviceExtension->CommandTimer,
1361 deltaTime,
1362 &deviceExtension->TimeOutDpc
1363 );
1364
1365 break;
1366
1367 //
1368 // Set the keyboard typematic rate and delay.
1369 //
1370
1371 case IOCTL_KEYBOARD_SET_TYPEMATIC:
1372
1373 I8xPrint((2, "I8042PRT-I8042StartIo: keyboard set typematic\n"));
1374
1375 //
1376 // Set up the context structure for the InitiateIo wrapper.
1377 //
1378
1379 keyboardInitiateContext.DeviceObject = DeviceObject;
1380 keyboardInitiateContext.FirstByte = SET_KEYBOARD_TYPEMATIC;
1381 keyboardInitiateContext.LastByte =
1382 I8xConvertTypematicParameters(
1383 ((PKEYBOARD_TYPEMATIC_PARAMETERS)
1384 Irp->AssociatedIrp.SystemBuffer)->Rate,
1385 ((PKEYBOARD_TYPEMATIC_PARAMETERS)
1386 Irp->AssociatedIrp.SystemBuffer)->Delay
1387 );
1388
1389 //
1390 // Call the InitiateIo wrapper synchronously. The wrapper
1391 // stores the context parameters in the device extension,
1392 // and then initiates the I/O operation, all synchronized
1393 // with the keyboard ISR.
1394 //
1395
1396 KeSynchronizeExecution(
1397 deviceExtension->KeyboardInterruptObject,
1398 (PKSYNCHRONIZE_ROUTINE) I8xKeyboardInitiateWrapper,
1399 (PVOID) &keyboardInitiateContext
1400 );
1401
1402 //
1403 // Start the 1-second command timer. InitiateIo changed
1404 // the TimerCount already.
1405 //
1406
1407 deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
1408 deltaTime.HighPart = -1;
1409
1410 (VOID) KeSetTimer(
1411 &deviceExtension->CommandTimer,
1412 deltaTime,
1413 &deviceExtension->TimeOutDpc
1414 );
1415
1416 break;
1417
1418
1419 default:
1420
1421 I8xPrint((2, "I8042PRT-I8042StartIo: INVALID REQUEST\n"));
1422
1423 //
1424 // Log an internal error. Note that we're calling the
1425 // error log DPC routine directly, rather than duplicating
1426 // code.
1427 //
1428
1429 I8042ErrorLogDpc(
1430 (PKDPC) NULL,
1431 DeviceObject,
1432 Irp,
1433 (PVOID) (ULONG) I8042_INVALID_STARTIO_REQUEST
1434 );
1435
1436 ASSERT(FALSE);
1437 break;
1438 }
1439
1440 I8xPrint((2, "I8042PRT-I8042StartIo: exit\n"));
1441
1442 return;
1443}
1444
1445
1446VOID
1447I8042TimeOutDpc(
1448 IN PKDPC Dpc,
1449 IN PDEVICE_OBJECT DeviceObject,
1450 IN PVOID SystemContext1,
1451 IN PVOID SystemContext2
1452 )
1453
1454/*++
1455
1456Routine Description:
1457
1458 This is the driver's command timeout routine. It is called when the
1459 command timer fires.
1460
1461Arguments:
1462
1463 Dpc - Not Used.
1464
1465 DeviceObject - Pointer to the device object.
1466
1467 SystemContext1 - Not Used.
1468
1469 SystemContext2 - Not Used.
1470
1471Return Value:
1472
1473 None. As a side-effect, the timeout counter is updated and an error
1474 is logged.
1475
1476--*/
1477
1478{
1479 PDEVICE_EXTENSION deviceExtension;
1480 KIRQL cancelIrql;
1481 TIMER_CONTEXT timerContext;
1482 PIRP irp;
1483 PIO_ERROR_LOG_PACKET errorLogEntry;
1484 PIO_STACK_LOCATION irpSp;
1485 LARGE_INTEGER deltaTime;
1486
1487 I8xPrint((3, "I8042PRT-I8042TimeOutDpc: enter\n"));
1488
1489 //
1490 // Get the device extension.
1491 //
1492
1493 deviceExtension = DeviceObject->DeviceExtension;
1494
1495 //
1496 // Acquire the cancel spinlock, verify that the CurrentIrp has not been
1497 // cancelled (i.e., CurrentIrp != NULL), set the cancel routine to NULL,
1498 // and release the cancel spinlock.
1499 //
1500
1501 IoAcquireCancelSpinLock(&cancelIrql);
1502 irp = DeviceObject->CurrentIrp;
1503 if (irp == NULL) {
1504 IoReleaseCancelSpinLock(cancelIrql);
1505 return;
1506 }
1507 IoSetCancelRoutine(irp, NULL);
1508 IoReleaseCancelSpinLock(cancelIrql);
1509
1510 //
1511 // If the TimerCounter == 0 on entry to this routine, the last packet
1512 // timed out and was completed. We just decrement TimerCounter
1513 // (synchronously) to indicate that we're no longer timing.
1514 //
1515 // If the TimerCounter indicates no timeout (I8042_ASYNC_NO_TIMEOUT)
1516 // on entry to this routine, there is no command being timed.
1517 //
1518
1519 timerContext.DeviceObject = DeviceObject;
1520 timerContext.TimerCounter = &deviceExtension->TimerCount;
1521
1522 KeSynchronizeExecution(
1523 deviceExtension->KeyboardInterruptObject,
1524 (PKSYNCHRONIZE_ROUTINE) I8xDecrementTimer,
1525 &timerContext
1526 );
1527
1528 if (timerContext.NewTimerCount == 0) {
1529
1530 //
1531 // Set up the IO Status Block prior to completing the request.
1532 //
1533
1534 DeviceObject->CurrentIrp->IoStatus.Information = 0;
1535 DeviceObject->CurrentIrp->IoStatus.Status = STATUS_IO_TIMEOUT;
1536
1537 //
1538 // Log a timeout error.
1539 //
1540
1541 errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
1542 DeviceObject,
1543 sizeof(IO_ERROR_LOG_PACKET)
1544 + (3 * sizeof(ULONG))
1545 );
1546
1547 if (errorLogEntry != NULL) {
1548
1549 errorLogEntry->ErrorCode = I8042_TIMEOUT;
1550 errorLogEntry->DumpDataSize = 3 * sizeof(ULONG);
1551 errorLogEntry->SequenceNumber =
1552 deviceExtension->KeyboardExtension.SequenceNumber;
1553 irpSp = IoGetCurrentIrpStackLocation(irp);
1554 errorLogEntry->MajorFunctionCode = irpSp->MajorFunction;
1555 errorLogEntry->IoControlCode =
1556 irpSp->Parameters.DeviceIoControl.IoControlCode;
1557 errorLogEntry->RetryCount = (UCHAR)
1558 deviceExtension->KeyboardExtension.ResendCount;
1559 errorLogEntry->UniqueErrorValue = 90;
1560 errorLogEntry->FinalStatus = STATUS_IO_TIMEOUT;
1561 errorLogEntry->DumpData[0] =
1562 deviceExtension->KeyboardExtension.CurrentOutput.State;
1563 errorLogEntry->DumpData[1] =
1564 deviceExtension->KeyboardExtension.CurrentOutput.FirstByte;
1565 errorLogEntry->DumpData[2] =
1566 deviceExtension->KeyboardExtension.CurrentOutput.LastByte;
1567
1568 IoWriteErrorLogEntry(errorLogEntry);
1569 }
1570
1571 //
1572 // Start the next packet and complete the request.
1573 //
1574
1575 IoStartNextPacket(DeviceObject, FALSE);
1576 IoCompleteRequest(irp, IO_KEYBOARD_INCREMENT);
1577
1578 } else {
1579
1580 //
1581 // Restart the command timer. Once started, the timer stops only
1582 // when the TimerCount goes to zero (indicating that the command
1583 // has timed out) or when explicitly cancelled in the completion
1584 // DPC (indicating that the command has successfully completed).
1585 //
1586
1587 deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
1588 deltaTime.HighPart = -1;
1589
1590 (VOID) KeSetTimer(
1591 &deviceExtension->CommandTimer,
1592 deltaTime,
1593 &deviceExtension->TimeOutDpc
1594 );
1595 }
1596
1597 I8xPrint((3, "I8042PRT-I8042TimeOutDpc: exit\n"));
1598}
1599
1600
1601#if DBG
1602VOID
1603I8xDebugPrint(
1604 ULONG DebugPrintLevel,
1605 PCCHAR DebugMessage,
1606 ...
1607 )
1608
1609/*++
1610
1611Routine Description:
1612
1613 Debug print routine.
1614
1615Arguments:
1616
1617 Debug print level between 0 and 3, with 3 being the most verbose.
1618
1619Return Value:
1620
1621 None.
1622
1623--*/
1624
1625{
1626 va_list ap;
1627
1628 va_start(ap, DebugMessage);
1629
1630 if (DebugPrintLevel <= i8042Debug) {
1631
1632 char buffer[128];
1633
1634 (VOID) vsprintf(buffer, DebugMessage, ap);
1635
1636 DbgPrint(buffer);
1637 }
1638
1639 va_end(ap);
1640
1641}
1642#endif
1643
1644
1645
1646VOID
1647I8xDecrementTimer(
1648 IN PTIMER_CONTEXT Context
1649 )
1650
1651/*++
1652
1653Routine Description:
1654
1655 This routine decrements the timeout counter. It is called from
1656 I8042TimeOutDpc.
1657
1658Arguments:
1659
1660 Context - Points to the context structure containing a pointer
1661 to the device object and a pointer to the timeout counter.
1662
1663Return Value:
1664
1665 None. As a side-effect, the timeout counter is updated.
1666
1667--*/
1668
1669{
1670 PDEVICE_OBJECT deviceObject;
1671 PDEVICE_EXTENSION deviceExtension;
1672
1673 deviceObject = Context->DeviceObject;
1674 deviceExtension = deviceObject->DeviceExtension;
1675
1676 //
1677 // Decrement the timeout counter.
1678 //
1679
1680 if (*(Context->TimerCounter) != I8042_ASYNC_NO_TIMEOUT)
1681 (*(Context->TimerCounter))--;
1682
1683 //
1684 // Return the decremented timer count in NewTimerCount. The
1685 // TimerCounter itself could change between the time this KeSynch'ed
1686 // routine returns to the TimeOutDpc, and the time the TimeOutDpc
1687 // looks at the value. The TimeOutDpc will use NewTimerCount.
1688 //
1689
1690 Context->NewTimerCount = *(Context->TimerCounter);
1691
1692 //
1693 // Reset the state and the resend count, if the timeout counter goes to 0.
1694 //
1695
1696 if (*(Context->TimerCounter) == 0) {
1697 deviceExtension->KeyboardExtension.CurrentOutput.State
1698 = Idle;
1699 deviceExtension->KeyboardExtension.ResendCount = 0;
1700 }
1701
1702}
1703
1704
1705VOID
1706I8xDpcVariableOperation(
1707 IN PVOID Context
1708 )
1709
1710/*++
1711
1712Routine Description:
1713
1714 This routine is called synchronously by the ISR DPC to perform an
1715 operation on the InterlockedDpcVariable. The operations that can be
1716 performed include increment, decrement, write, and read. The ISR
1717 itself reads and writes the InterlockedDpcVariable without calling this
1718 routine.
1719
1720Arguments:
1721
1722 Context - Pointer to a structure containing the address of the variable
1723 to be operated on, the operation to perform, and the address at
1724 which to copy the resulting value of the variable (the latter is also
1725 used to pass in the value to write to the variable, on a write
1726 operation).
1727
1728Return Value:
1729
1730 None.
1731
1732--*/
1733
1734{
1735 PVARIABLE_OPERATION_CONTEXT operationContext = Context;
1736
1737 I8xPrint((3,"I8042PRT-I8xDpcVariableOperation: enter\n"));
1738 I8xPrint((
1739 3,
1740 "\tPerforming %s at 0x%x (current value 0x%x)\n",
1741 (operationContext->Operation == IncrementOperation)? "increment":
1742 (operationContext->Operation == DecrementOperation)? "decrement":
1743 (operationContext->Operation == WriteOperation)? "write":
1744 (operationContext->Operation == ReadOperation)? "read":"",
1745 operationContext->VariableAddress,
1746 *(operationContext->VariableAddress)
1747 ));
1748
1749 //
1750 // Perform the specified operation at the specified address.
1751 //
1752
1753 switch(operationContext->Operation) {
1754 case IncrementOperation:
1755 *(operationContext->VariableAddress) += 1;
1756 break;
1757 case DecrementOperation:
1758 *(operationContext->VariableAddress) -= 1;
1759 break;
1760 case ReadOperation:
1761 break;
1762 case WriteOperation:
1763 I8xPrint((
1764 3,
1765 "\tWriting 0x%x\n",
1766 *(operationContext->NewValue)
1767 ));
1768 *(operationContext->VariableAddress) =
1769 *(operationContext->NewValue);
1770 break;
1771 default:
1772 ASSERT(FALSE);
1773 break;
1774 }
1775
1776 *(operationContext->NewValue) = *(operationContext->VariableAddress);
1777
1778 I8xPrint((
1779 3,
1780 "I8042PRT-I8xDpcVariableOperation: exit with value 0x%x\n",
1781 *(operationContext->NewValue)
1782 ));
1783}
1784
1785
1786VOID
1787I8xGetDataQueuePointer(
1788 IN PVOID Context
1789 )
1790
1791/*++
1792
1793Routine Description:
1794
1795 This routine is called synchronously to get the current DataIn and DataOut
1796 pointers for the port InputData queue.
1797
1798Arguments:
1799
1800 Context - Pointer to a structure containing the device extension,
1801 device type, address at which to store the current DataIn pointer,
1802 and the address at which to store the current DataOut pointer.
1803
1804Return Value:
1805
1806 None.
1807
1808--*/
1809
1810{
1811 PDEVICE_EXTENSION deviceExtension;
1812 CCHAR deviceType;
1813
1814 I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: enter\n"));
1815
1816 //
1817 // Get address of device extension.
1818 //
1819
1820 deviceExtension = (PDEVICE_EXTENSION)
1821 ((PGET_DATA_POINTER_CONTEXT) Context)->DeviceExtension;
1822 deviceType = (CCHAR) ((PGET_DATA_POINTER_CONTEXT) Context)->DeviceType;
1823
1824 //
1825 // Get the DataIn and DataOut pointers for the indicated device.
1826 //
1827
1828 if (deviceType == KeyboardDeviceType) {
1829 I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: keyboard\n"));
1830 I8xPrint((
1831 3,
1832 "I8042PRT-I8xGetDataQueuePointer: DataIn 0x%x, DataOut 0x%x\n",
1833 deviceExtension->KeyboardExtension.DataIn,
1834 deviceExtension->KeyboardExtension.DataOut
1835 ));
1836 ((PGET_DATA_POINTER_CONTEXT) Context)->DataIn =
1837 deviceExtension->KeyboardExtension.DataIn;
1838 ((PGET_DATA_POINTER_CONTEXT) Context)->DataOut =
1839 deviceExtension->KeyboardExtension.DataOut;
1840 ((PGET_DATA_POINTER_CONTEXT) Context)->InputCount =
1841 deviceExtension->KeyboardExtension.InputCount;
1842 } else if (deviceType == MouseDeviceType) {
1843 I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: mouse\n"));
1844 I8xPrint((
1845 3,
1846 "I8042PRT-I8xGetDataQueuePointer: DataIn 0x%x, DataOut 0x%x\n",
1847 deviceExtension->MouseExtension.DataIn,
1848 deviceExtension->MouseExtension.DataOut
1849 ));
1850 ((PGET_DATA_POINTER_CONTEXT) Context)->DataIn =
1851 deviceExtension->MouseExtension.DataIn;
1852 ((PGET_DATA_POINTER_CONTEXT) Context)->DataOut =
1853 deviceExtension->MouseExtension.DataOut;
1854 ((PGET_DATA_POINTER_CONTEXT) Context)->InputCount =
1855 deviceExtension->MouseExtension.InputCount;
1856 } else {
1857 ASSERT(FALSE);
1858 }
1859
1860 I8xPrint((3,"I8042PRT-I8xGetDataQueuePointer: exit\n"));
1861}
1862
1863
1864VOID
1865I8xInitializeDataQueue (
1866 IN PVOID Context
1867 )
1868
1869/*++
1870
1871Routine Description:
1872
1873 This routine initializes the input data queue for the indicated device.
1874 This routine is called via KeSynchronization, except when called from
1875 the initialization routine.
1876
1877Arguments:
1878
1879 Context - Pointer to a structure containing the device extension and
1880 the device type.
1881
1882Return Value:
1883
1884 None.
1885
1886--*/
1887
1888{
1889
1890 PDEVICE_EXTENSION deviceExtension;
1891 CCHAR deviceType;
1892
1893 I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: enter\n"));
1894
1895 //
1896 // Get address of device extension.
1897 //
1898
1899 deviceExtension = (PDEVICE_EXTENSION)
1900 ((PI8042_INITIALIZE_DATA_CONTEXT) Context)->DeviceExtension;
1901 deviceType = (CCHAR) ((PI8042_INITIALIZE_DATA_CONTEXT) Context)->DeviceType;
1902
1903 //
1904 // Initialize the input data queue for the indicated device.
1905 //
1906
1907 if (deviceType == KeyboardDeviceType) {
1908 deviceExtension->KeyboardExtension.InputCount = 0;
1909 deviceExtension->KeyboardExtension.DataIn =
1910 deviceExtension->KeyboardExtension.InputData;
1911 deviceExtension->KeyboardExtension.DataOut =
1912 deviceExtension->KeyboardExtension.InputData;
1913 deviceExtension->KeyboardExtension.OkayToLogOverflow = TRUE;
1914 I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: keyboard\n"));
1915 } else if (deviceType == MouseDeviceType) {
1916 deviceExtension->MouseExtension.InputCount = 0;
1917 deviceExtension->MouseExtension.DataIn =
1918 deviceExtension->MouseExtension.InputData;
1919 deviceExtension->MouseExtension.DataOut =
1920 deviceExtension->MouseExtension.InputData;
1921 deviceExtension->MouseExtension.OkayToLogOverflow = TRUE;
1922 I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: mouse\n"));
1923 } else {
1924 ASSERT(FALSE);
1925 }
1926
1927 I8xPrint((3,"I8042PRT-I8xInitializeDataQueue: exit\n"));
1928
1929}
1930
1931
1932VOID
1933I8xLogError(
1934 IN PDEVICE_OBJECT DeviceObject,
1935 IN NTSTATUS ErrorCode,
1936 IN ULONG UniqueErrorValue,
1937 IN NTSTATUS FinalStatus,
1938 IN PULONG DumpData,
1939 IN ULONG DumpCount
1940 )
1941
1942/*++
1943
1944Routine Description:
1945
1946 This routine contains common code to write an error log entry. It is
1947 called from other routines, especially I8xInitializeKeyboard, to avoid
1948 duplication of code. Note that some routines continue to have their
1949 own error logging code (especially in the case where the error logging
1950 can be localized and/or the routine has more data because there is
1951 and IRP).
1952
1953Arguments:
1954
1955 DeviceObject - Pointer to the device object.
1956
1957 ErrorCode - The error code for the error log packet.
1958
1959 UniqueErrorValue - The unique error value for the error log packet.
1960
1961 FinalStatus - The final status of the operation for the error log packet.
1962
1963 DumpData - Pointer to an array of dump data for the error log packet.
1964
1965 DumpCount - The number of entries in the dump data array.
1966
1967
1968Return Value:
1969
1970 None.
1971
1972--*/
1973
1974{
1975 PIO_ERROR_LOG_PACKET errorLogEntry;
1976 ULONG i;
1977
1978 errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(
1979 DeviceObject,
1980 (UCHAR)
1981 (sizeof(IO_ERROR_LOG_PACKET)
1982 + (DumpCount * sizeof(ULONG)))
1983 );
1984
1985 if (errorLogEntry != NULL) {
1986
1987 errorLogEntry->ErrorCode = ErrorCode;
1988 errorLogEntry->DumpDataSize = (USHORT) (DumpCount * sizeof(ULONG));
1989 errorLogEntry->SequenceNumber = 0;
1990 errorLogEntry->MajorFunctionCode = 0;
1991 errorLogEntry->IoControlCode = 0;
1992 errorLogEntry->RetryCount = 0;
1993 errorLogEntry->UniqueErrorValue = UniqueErrorValue;
1994 errorLogEntry->FinalStatus = FinalStatus;
1995 for (i = 0; i < DumpCount; i++)
1996 errorLogEntry->DumpData[i] = DumpData[i];
1997
1998 IoWriteErrorLogEntry(errorLogEntry);
1999 }
2000}
2001
2002
2003VOID
2004I8xSetDataQueuePointer(
2005 IN PVOID Context
2006 )
2007
2008/*++
2009
2010Routine Description:
2011
2012 This routine is called synchronously to set the DataOut pointer
2013 and InputCount for the port InputData queue.
2014
2015Arguments:
2016
2017 Context - Pointer to a structure containing the device extension,
2018 device type, and the new DataOut value for the port InputData queue.
2019
2020Return Value:
2021
2022 None.
2023
2024--*/
2025
2026{
2027 PDEVICE_EXTENSION deviceExtension;
2028 CCHAR deviceType;
2029
2030 I8xPrint((3,"I8042PRT-I8xSetDataQueuePointer: enter\n"));
2031
2032 //
2033 // Get address of device extension.
2034 //
2035
2036 deviceExtension = (PDEVICE_EXTENSION)
2037 ((PSET_DATA_POINTER_CONTEXT) Context)->DeviceExtension;
2038 deviceType = (CCHAR) ((PSET_DATA_POINTER_CONTEXT) Context)->DeviceType;
2039
2040 //
2041 // Set the DataOut pointer for the indicated device.
2042 //
2043
2044 if (deviceType == KeyboardDeviceType) {
2045 I8xPrint((
2046 3,
2047 "I8042PRT-I8xSetDataQueuePointer: old keyboard DataOut 0x%x, InputCount %d\n",
2048 deviceExtension->KeyboardExtension.DataOut,
2049 deviceExtension->KeyboardExtension.InputCount
2050 ));
2051 deviceExtension->KeyboardExtension.DataOut =
2052 ((PSET_DATA_POINTER_CONTEXT) Context)->DataOut;
2053 deviceExtension->KeyboardExtension.InputCount -=
2054 ((PSET_DATA_POINTER_CONTEXT) Context)->InputCount;
2055 if (deviceExtension->KeyboardExtension.InputCount == 0) {
2056
2057 //
2058 // Reset the flag that determines whether it is time to log
2059 // queue overflow errors. We don't want to log errors too often.
2060 // Instead, log an error on the first overflow that occurs after
2061 // the ring buffer has been emptied, and then stop logging errors
2062 // until it gets cleared out and overflows again.
2063 //
2064
2065 I8xPrint((
2066 2,
2067 "I8042PRT-I8xSetDataQueuePointer: Okay to log keyboard overflow\n"
2068 ));
2069 deviceExtension->KeyboardExtension.OkayToLogOverflow = TRUE;
2070 }
2071 I8xPrint((
2072 3,
2073 "I8042PRT-I8xSetDataQueuePointer: new keyboard DataOut 0x%x, InputCount %d\n",
2074 deviceExtension->KeyboardExtension.DataOut,
2075 deviceExtension->KeyboardExtension.InputCount
2076 ));
2077 } else if (deviceType == MouseDeviceType) {
2078 I8xPrint((
2079 3,
2080 "I8042PRT-I8xSetDataQueuePointer: old mouse DataOut 0x%x, InputCount %d\n",
2081 deviceExtension->MouseExtension.DataOut,
2082 deviceExtension->MouseExtension.InputCount
2083 ));
2084 deviceExtension->MouseExtension.DataOut =
2085 ((PSET_DATA_POINTER_CONTEXT) Context)->DataOut;
2086 deviceExtension->MouseExtension.InputCount -=
2087 ((PSET_DATA_POINTER_CONTEXT) Context)->InputCount;
2088 if (deviceExtension->MouseExtension.InputCount == 0) {
2089
2090 //
2091 // Reset the flag that determines whether it is time to log
2092 // queue overflow errors. We don't want to log errors too often.
2093 // Instead, log an error on the first overflow that occurs after
2094 // the ring buffer has been emptied, and then stop logging errors
2095 // until it gets cleared out and overflows again.
2096 //
2097
2098 I8xPrint((
2099 2,
2100 "I8042PRT-I8xSetDataQueuePointer: Okay to log mouse overflow\n"
2101 ));
2102 deviceExtension->MouseExtension.OkayToLogOverflow = TRUE;
2103 }
2104 I8xPrint((
2105 3,
2106 "I8042PRT-I8xSetDataQueuePointer: new mouse DataOut 0x%x, InputCount %d\n",
2107 deviceExtension->MouseExtension.DataOut,
2108 deviceExtension->MouseExtension.InputCount
2109 ));
2110 } else {
2111 ASSERT(FALSE);
2112 }
2113
2114 I8xPrint((3,"I8042PRT-I8xSetDataQueuePointer: exit\n"));
2115}
2116
2117#ifdef JAPAN
2118NTSTATUS
2119I8xCreateSymbolicLink(
2120 IN PWCHAR SymbolicLinkName,
2121 IN ULONG SymbolicLinkInteger,
2122 IN PUNICODE_STRING DeviceName
2123 )
2124{
2125 #define STRING_LENGTH 60
2126
2127 NTSTATUS status = STATUS_SUCCESS;
2128 WCHAR ntNumberBuffer[STRING_LENGTH];
2129 UNICODE_STRING ntNumberUnicodeString;
2130 WCHAR deviceLinkBuffer[STRING_LENGTH];
2131 UNICODE_STRING deviceLinkUnicodeString;
2132
2133 //
2134 // Set up space for the port's full keyboard device object name.
2135 //
2136
2137 ntNumberUnicodeString.Buffer = ntNumberBuffer;
2138 ntNumberUnicodeString.Length = 0;
2139 ntNumberUnicodeString.MaximumLength = STRING_LENGTH;
2140
2141 status = RtlIntegerToUnicodeString(
2142 SymbolicLinkInteger + 1,
2143 10,
2144 &ntNumberUnicodeString);
2145 if (!NT_SUCCESS(status)) {
2146 return status;
2147 }
2148
2149 deviceLinkUnicodeString.Buffer = deviceLinkBuffer;
2150 deviceLinkUnicodeString.Length = 0;
2151 deviceLinkUnicodeString.MaximumLength = STRING_LENGTH;
2152
2153 status = RtlAppendUnicodeToString(
2154 &deviceLinkUnicodeString,
2155 SymbolicLinkName);
2156 if (!NT_SUCCESS(status)) {
2157 return status;
2158 }
2159
2160 status = RtlAppendUnicodeStringToString(
2161 &deviceLinkUnicodeString,
2162 &ntNumberUnicodeString);
2163 if (!NT_SUCCESS(status)) {
2164 return status;
2165 }
2166
2167 status = IoCreateSymbolicLink(
2168 &deviceLinkUnicodeString,
2169 DeviceName
2170 );
2171
2172 if (!NT_SUCCESS(status)) {
2173 I8xPrint((
2174 1,
2175 "I8042PRT-I8xCreateSymbolicLink: Could not create symbolic link = %ws\n",
2176 DeviceName->Buffer
2177 ));
2178 return status;
2179 }
2180
2181 return status;
2182}
2183
2184#if defined(i386)
2185// Fujitsu Sep.08.1994
2186// We want to write debugging information to the file except stop error.
2187
2188VOID
2189I8xServiceCrashDump(
2190 IN PDEVICE_EXTENSION DeviceExtension,
2191 IN PUNICODE_STRING RegistryPath,
2192 IN PUNICODE_STRING KeyboardDeviceName,
2193 IN PUNICODE_STRING PointerDeviceName
2194 )
2195
2196/*++
2197
2198Routine Description:
2199
2200 This routine retrieves this driver's service parameters information
2201 from the registry.
2202
2203Arguments:
2204
2205 DeviceExtension - Pointer to the device extension.
2206
2207 RegistryPath - Pointer to the null-terminated Unicode name of the
2208 registry path for this driver.
2209
2210 KeyboardDeviceName - Pointer to the Unicode string that will receive
2211 the keyboard port device name.
2212
2213 PointerDeviceName - Pointer to the Unicode string that will receive
2214 the pointer port device name.
2215
2216Return Value:
2217
2218 None. As a side-effect, sets fields in DeviceExtension->Dump1Keys
2219 & DeviceExtension->Dump2Key.
2220
2221--*/
2222
2223{
2224 PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
2225 UNICODE_STRING parametersPath;
2226 LONG defaultDump1Keys = 0;
2227 LONG Dump1Keys;
2228 LONG defaultDump2Key = 0;
2229 LONG Dump2Key;
2230 UNICODE_STRING defaultPointerName;
2231 UNICODE_STRING defaultKeyboardName;
2232 NTSTATUS status = STATUS_SUCCESS;
2233 PWSTR path = NULL;
2234 USHORT queriesPlusOne = 3;
2235
2236 parametersPath.Buffer = NULL;
2237
2238 //
2239 // Registry path is already null-terminated, so just use it.
2240 //
2241
2242 path = RegistryPath->Buffer;
2243
2244 if (NT_SUCCESS(status)) {
2245
2246 //
2247 // Allocate the Rtl query table.
2248 //
2249
2250 parameters = ExAllocatePool(
2251 PagedPool,
2252 sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2253 );
2254
2255 if (!parameters) {
2256
2257 I8xPrint((
2258 1,
2259 "I8042PRT-I8xServiceCrashDump: Couldn't allocate table for Rtl query to parameters for %ws\n",
2260 path
2261 ));
2262
2263 status = STATUS_UNSUCCESSFUL;
2264
2265 } else {
2266
2267 RtlZeroMemory(
2268 parameters,
2269 sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne
2270 );
2271
2272 //
2273 // Form a path to this driver's Parameters subkey.
2274 //
2275
2276 RtlInitUnicodeString(
2277 &parametersPath,
2278 NULL
2279 );
2280
2281 parametersPath.MaximumLength = RegistryPath->Length +
2282 sizeof(L"\\Crashdump");
2283
2284 parametersPath.Buffer = ExAllocatePool(
2285 PagedPool,
2286 parametersPath.MaximumLength
2287 );
2288
2289 if (!parametersPath.Buffer) {
2290
2291 I8xPrint((
2292 1,
2293 "I8042PRT-I8xServiceCrashDump: Couldn't allocate string for path to parameters for %ws\n",
2294 path
2295 ));
2296
2297 status = STATUS_UNSUCCESSFUL;
2298
2299 }
2300 }
2301 }
2302
2303 if (NT_SUCCESS(status)) {
2304
2305 //
2306 // Form the parameters path.
2307 //
2308
2309 RtlZeroMemory(
2310 parametersPath.Buffer,
2311 parametersPath.MaximumLength
2312 );
2313 RtlAppendUnicodeToString(
2314 &parametersPath,
2315 path
2316 );
2317 RtlAppendUnicodeToString(
2318 &parametersPath,
2319 L"\\Crashdump"
2320 );
2321
2322 I8xPrint((
2323 1,
2324 "I8042PRT-I8xServiceCrashDump: crashdump path is %ws\n",
2325 parametersPath.Buffer
2326 ));
2327
2328 //
2329 // Form the default port device names, in case they are not
2330 // specified in the registry.
2331 //
2332
2333 RtlInitUnicodeString(
2334 &defaultKeyboardName,
2335 DD_KEYBOARD_PORT_BASE_NAME_U
2336 );
2337 RtlInitUnicodeString(
2338 &defaultPointerName,
2339 DD_POINTER_PORT_BASE_NAME_U
2340 );
2341
2342 //
2343 // Gather all of the "user specified" information from
2344 // the registry.
2345 //
2346
2347 parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
2348 parameters[0].Name = L"Dump1Keys";
2349 parameters[0].EntryContext = &Dump1Keys;
2350 parameters[0].DefaultType = REG_DWORD;
2351 parameters[0].DefaultData = &defaultDump1Keys;
2352 parameters[0].DefaultLength = sizeof(LONG);
2353
2354 parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
2355 parameters[1].Name = L"Dump2Key";
2356 parameters[1].EntryContext = &Dump2Key;
2357 parameters[1].DefaultType = REG_DWORD;
2358 parameters[1].DefaultData = &defaultDump2Key;
2359 parameters[1].DefaultLength = sizeof(LONG);
2360
2361 status = RtlQueryRegistryValues(
2362 RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
2363 parametersPath.Buffer,
2364 parameters,
2365 NULL,
2366 NULL
2367 );
2368
2369 if (!NT_SUCCESS(status)) {
2370 I8xPrint((
2371 1,
2372 "I8042PRT-I8xServiceCrashDump: RtlQueryRegistryValues failed with 0x%x\n",
2373 status
2374 ));
2375 }
2376 }
2377
2378 if (!NT_SUCCESS(status)) {
2379
2380 //
2381 // Go ahead and assign driver defaults.
2382 //
2383
2384 DeviceExtension->Dump1Keys = 0;
2385 DeviceExtension->Dump2Key = 0;
2386 } else {
2387 DeviceExtension->Dump1Keys = Dump1Keys;
2388 DeviceExtension->Dump2Key = Dump2Key;
2389 }
2390
2391 I8xPrint((
2392 1,
2393 "I8042PRT-I8xServiceCrashDump: Keyboard port base name = %ws\n",
2394 KeyboardDeviceName->Buffer
2395 ));
2396
2397 I8xPrint((
2398 1,
2399 "I8042PRT-I8xServiceCrashDump: Pointer port base name = %ws\n",
2400 PointerDeviceName->Buffer
2401 ));
2402
2403 I8xPrint((
2404 1,
2405 "I8042PRT-I8xServiceCrashDump: Dump1Keys = %d\n",
2406 DeviceExtension->Dump1Keys
2407 ));
2408 I8xPrint((
2409 1,
2410 "I8042PRT-I8xServiceCrashDump: Dump2Key = %d\n",
2411 DeviceExtension->Dump2Key
2412 ));
2413
2414 //
2415 // Free the allocated memory before returning.
2416 //
2417
2418 if (parametersPath.Buffer)
2419 ExFreePool(parametersPath.Buffer);
2420 if (parameters)
2421 ExFreePool(parameters);
2422
2423}
2424#endif // i386
2425#endif // JAPAN
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette