1 |
|
---|
2 | /*++
|
---|
3 |
|
---|
4 | Copyright (c) 1990, 1991, 1992, 1993 Microsoft Corporation
|
---|
5 |
|
---|
6 | Module Name:
|
---|
7 |
|
---|
8 | kbddep.c
|
---|
9 |
|
---|
10 | Abstract:
|
---|
11 |
|
---|
12 | The initialization and hardware-dependent portions of
|
---|
13 | the Intel i8042 port driver which are specific to the
|
---|
14 | keyboard.
|
---|
15 |
|
---|
16 | Environment:
|
---|
17 |
|
---|
18 | Kernel mode only.
|
---|
19 |
|
---|
20 | Notes:
|
---|
21 |
|
---|
22 | NOTES: (Future/outstanding issues)
|
---|
23 |
|
---|
24 | - Powerfail not implemented.
|
---|
25 |
|
---|
26 | - Consolidate duplicate code, where possible and appropriate.
|
---|
27 |
|
---|
28 | Revision History:
|
---|
29 |
|
---|
30 | --*/
|
---|
31 |
|
---|
32 | #include "stdarg.h"
|
---|
33 | #include "stdio.h"
|
---|
34 | #include "string.h"
|
---|
35 | #include "ntddk.h"
|
---|
36 | #include "i8042prt.h"
|
---|
37 | #include "i8042log.h"
|
---|
38 |
|
---|
39 | //
|
---|
40 | // Use the alloc_text pragma to specify the driver initialization routines
|
---|
41 | // (they can be paged out).
|
---|
42 | //
|
---|
43 |
|
---|
44 | #ifdef ALLOC_PRAGMA
|
---|
45 | #pragma alloc_text(INIT,I8xKeyboardConfiguration)
|
---|
46 | #pragma alloc_text(INIT,I8xKeyboardPeripheralCallout)
|
---|
47 | #pragma alloc_text(INIT,I8xInitializeKeyboard)
|
---|
48 | #endif
|
---|
49 |
|
---|
50 | |
---|
51 |
|
---|
52 | BOOLEAN
|
---|
53 | I8042KeyboardInterruptService(
|
---|
54 | IN PKINTERRUPT Interrupt,
|
---|
55 | IN PVOID Context
|
---|
56 | )
|
---|
57 |
|
---|
58 | /*++
|
---|
59 |
|
---|
60 | Routine Description:
|
---|
61 |
|
---|
62 | This is the interrupt service routine for the keyboard device when
|
---|
63 | scan code set 1 is in use.
|
---|
64 |
|
---|
65 | Arguments:
|
---|
66 |
|
---|
67 | Interrupt - A pointer to the interrupt object for this interrupt.
|
---|
68 |
|
---|
69 | Context - A pointer to the device object.
|
---|
70 |
|
---|
71 | Return Value:
|
---|
72 |
|
---|
73 | Returns TRUE if the interrupt was expected (and therefore processed);
|
---|
74 | otherwise, FALSE is returned.
|
---|
75 |
|
---|
76 | --*/
|
---|
77 |
|
---|
78 | {
|
---|
79 | UCHAR scanCode;
|
---|
80 | PDEVICE_EXTENSION deviceExtension;
|
---|
81 | PDEVICE_OBJECT deviceObject;
|
---|
82 | KEYBOARD_SCAN_STATE *scanState;
|
---|
83 | PKEYBOARD_INPUT_DATA input;
|
---|
84 | ULONG i;
|
---|
85 |
|
---|
86 | UNREFERENCED_PARAMETER(Interrupt);
|
---|
87 |
|
---|
88 | I8xPrint((2, "I8042PRT-I8042KeyboardInterruptService: enter\n"));
|
---|
89 |
|
---|
90 | //
|
---|
91 | // Get the device extension.
|
---|
92 | //
|
---|
93 |
|
---|
94 | deviceObject = (PDEVICE_OBJECT) Context;
|
---|
95 | deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
|
---|
96 |
|
---|
97 | //
|
---|
98 | // Verify that this device really interrupted. Check the status
|
---|
99 | // register. The Output Buffer Full bit should be set, and the
|
---|
100 | // Auxiliary Device Output Buffer Full bit should be clear.
|
---|
101 | //
|
---|
102 |
|
---|
103 | if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort])
|
---|
104 | & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
|
---|
105 | != OUTPUT_BUFFER_FULL) {
|
---|
106 |
|
---|
107 | //
|
---|
108 | // Stall and then try again. The Olivetti MIPS machine
|
---|
109 | // sometimes gets an interrupt before the status
|
---|
110 | // register is set. They do this for DOS compatibility (some
|
---|
111 | // DOS apps do things in polled mode, until they see a character
|
---|
112 | // in the keyboard buffer at which point they expect to get
|
---|
113 | // an interrupt???).
|
---|
114 | //
|
---|
115 |
|
---|
116 | for (i = 0; i < (ULONG)deviceExtension->Configuration.PollStatusIterations; i++) {
|
---|
117 | KeStallExecutionProcessor(1);
|
---|
118 | if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort])
|
---|
119 | & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
|
---|
120 | == (OUTPUT_BUFFER_FULL))
|
---|
121 | break;
|
---|
122 | }
|
---|
123 |
|
---|
124 | if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort])
|
---|
125 | & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
|
---|
126 | != (OUTPUT_BUFFER_FULL)) {
|
---|
127 |
|
---|
128 | //
|
---|
129 | // Not our interrupt.
|
---|
130 | //
|
---|
131 | // NOTE: If the keyboard has not yet been "enabled", go ahead
|
---|
132 | // and read a byte from the data port anyway.
|
---|
133 | // This fixes weirdness on some Gateway machines, where
|
---|
134 | // we get an interrupt sometime during driver initialization
|
---|
135 | // after the interrupt is connected, but the output buffer
|
---|
136 | // full bit never gets set.
|
---|
137 | //
|
---|
138 |
|
---|
139 | I8xPrint((
|
---|
140 | 1,
|
---|
141 | "I8042PRT-I8042KeyboardInterruptService: not our interrupt!\n"
|
---|
142 | ));
|
---|
143 |
|
---|
144 | if (deviceExtension->KeyboardEnableCount == 0) {
|
---|
145 | scanCode =
|
---|
146 | I8X_GET_DATA_BYTE(deviceExtension->DeviceRegisters[DataPort]);
|
---|
147 | }
|
---|
148 |
|
---|
149 | return(FALSE);
|
---|
150 | }
|
---|
151 | }
|
---|
152 |
|
---|
153 | //
|
---|
154 | // The interrupt is valid. Read the byte from the i8042 data port.
|
---|
155 | //
|
---|
156 |
|
---|
157 | I8xGetByteAsynchronous(
|
---|
158 | (CCHAR) KeyboardDeviceType,
|
---|
159 | deviceExtension,
|
---|
160 | &scanCode
|
---|
161 | );
|
---|
162 |
|
---|
163 | I8xPrint((
|
---|
164 | 2,
|
---|
165 | "I8042PRT-I8042KeyboardInterruptService: scanCode 0x%x\n",
|
---|
166 | scanCode
|
---|
167 | ));
|
---|
168 |
|
---|
169 | //
|
---|
170 | // Take the appropriate action, depending on whether the byte read
|
---|
171 | // is a keyboard command response or a real scan code.
|
---|
172 | //
|
---|
173 |
|
---|
174 | switch(scanCode) {
|
---|
175 |
|
---|
176 | //
|
---|
177 | // The keyboard controller requests a resend. If the resend count
|
---|
178 | // has not been exceeded, re-initiate the I/O operation.
|
---|
179 | //
|
---|
180 |
|
---|
181 | case RESEND:
|
---|
182 |
|
---|
183 | I8xPrint((
|
---|
184 | 3,
|
---|
185 | "I8042PRT-I8042KeyboardInterruptService: RESEND, retries = %d\n",
|
---|
186 | deviceExtension->KeyboardExtension.ResendCount + 1
|
---|
187 | ));
|
---|
188 |
|
---|
189 | //
|
---|
190 | // If the timer count is zero, don't process the interrupt
|
---|
191 | // further. The timeout routine will complete this request.
|
---|
192 | //
|
---|
193 |
|
---|
194 | if (deviceExtension->TimerCount == 0) {
|
---|
195 | break;
|
---|
196 | }
|
---|
197 |
|
---|
198 | //
|
---|
199 | // Reset the timeout value to indicate no timeout.
|
---|
200 | //
|
---|
201 |
|
---|
202 | deviceExtension->TimerCount = I8042_ASYNC_NO_TIMEOUT;
|
---|
203 |
|
---|
204 | //
|
---|
205 | // If the maximum number of retries has not been exceeded,
|
---|
206 | // re-initiate the operation; otherwise, queue the DPC to
|
---|
207 | // complete this request.
|
---|
208 | //
|
---|
209 |
|
---|
210 | if ((deviceExtension->KeyboardExtension.CurrentOutput.State==Idle)
|
---|
211 | || (deviceObject->CurrentIrp == NULL)) {
|
---|
212 |
|
---|
213 | //
|
---|
214 | // We weren't sending a command or parameter to the hardware.
|
---|
215 | // This must be a scan code. I hear the Brazilian keyboard
|
---|
216 | // actually uses this.
|
---|
217 | //
|
---|
218 |
|
---|
219 | goto ScanCodeCase;
|
---|
220 |
|
---|
221 | } else if (deviceExtension->KeyboardExtension.ResendCount
|
---|
222 | < deviceExtension->Configuration.ResendIterations) {
|
---|
223 |
|
---|
224 | deviceExtension->KeyboardExtension.ResendCount += 1;
|
---|
225 | I8xKeyboardInitiateIo((PVOID) deviceObject);
|
---|
226 |
|
---|
227 | } else {
|
---|
228 |
|
---|
229 | deviceExtension->KeyboardExtension.CurrentOutput.State = Idle;
|
---|
230 |
|
---|
231 | KeInsertQueueDpc(
|
---|
232 | &deviceExtension->RetriesExceededDpc,
|
---|
233 | deviceObject->CurrentIrp,
|
---|
234 | NULL
|
---|
235 | );
|
---|
236 | }
|
---|
237 |
|
---|
238 | break;
|
---|
239 |
|
---|
240 | //
|
---|
241 | // The keyboard controller has acknowledged a previous send.
|
---|
242 | // If there are more bytes to send for the current packet, initiate
|
---|
243 | // the next send operation. Otherwise, queue the completion DPC.
|
---|
244 | //
|
---|
245 |
|
---|
246 | case ACKNOWLEDGE:
|
---|
247 |
|
---|
248 | I8xPrint((
|
---|
249 | 3,
|
---|
250 | "I8042PRT-I8042KeyboardInterruptService: ACK, "
|
---|
251 | ));
|
---|
252 |
|
---|
253 | //
|
---|
254 | // If the timer count is zero, don't process the interrupt
|
---|
255 | // further. The timeout routine will complete this request.
|
---|
256 | //
|
---|
257 |
|
---|
258 | if (deviceExtension->TimerCount == 0) {
|
---|
259 | break;
|
---|
260 | }
|
---|
261 |
|
---|
262 | //
|
---|
263 | // Reset the timeout value to indicate no timeout.
|
---|
264 | //
|
---|
265 |
|
---|
266 | deviceExtension->TimerCount = I8042_ASYNC_NO_TIMEOUT;
|
---|
267 |
|
---|
268 | //
|
---|
269 | // Reset resend count.
|
---|
270 | //
|
---|
271 |
|
---|
272 | deviceExtension->KeyboardExtension.ResendCount = 0;
|
---|
273 |
|
---|
274 | if (deviceExtension->KeyboardExtension.CurrentOutput.State
|
---|
275 | == SendFirstByte) {
|
---|
276 |
|
---|
277 | //
|
---|
278 | // We've successfully sent the first byte of a 2-byte
|
---|
279 | // command sequence. Initiate a send of the second byte.
|
---|
280 | //
|
---|
281 |
|
---|
282 | I8xPrint((
|
---|
283 | 3,
|
---|
284 | "now initiate send of last byte\n"
|
---|
285 | ));
|
---|
286 |
|
---|
287 | deviceExtension->KeyboardExtension.CurrentOutput.State =
|
---|
288 | SendLastByte;
|
---|
289 |
|
---|
290 | I8xKeyboardInitiateIo((PVOID) deviceObject);
|
---|
291 |
|
---|
292 | } else if (deviceExtension->KeyboardExtension.CurrentOutput.State
|
---|
293 | == SendLastByte) {
|
---|
294 |
|
---|
295 | //
|
---|
296 | // We've successfully sent all bytes in the command sequence.
|
---|
297 | // Reset the current state and queue the completion DPC.
|
---|
298 | //
|
---|
299 |
|
---|
300 | I8xPrint((
|
---|
301 | 3,
|
---|
302 | "all bytes have been sent\n"
|
---|
303 | ));
|
---|
304 |
|
---|
305 | deviceExtension->KeyboardExtension.CurrentOutput.State = Idle;
|
---|
306 |
|
---|
307 | IoRequestDpc(
|
---|
308 | deviceObject,
|
---|
309 | deviceObject->CurrentIrp,
|
---|
310 | NULL
|
---|
311 | );
|
---|
312 |
|
---|
313 | } else {
|
---|
314 | I8xPrint((
|
---|
315 | 1,
|
---|
316 | "unexpected, State is 0x%x\n",
|
---|
317 | deviceExtension->KeyboardExtension.CurrentOutput.State
|
---|
318 | ));
|
---|
319 | //
|
---|
320 | // Queue a DPC to log an internal driver error.
|
---|
321 | //
|
---|
322 |
|
---|
323 | KeInsertQueueDpc(
|
---|
324 | &deviceExtension->ErrorLogDpc,
|
---|
325 | (PIRP) NULL,
|
---|
326 | (PVOID) (ULONG) I8042_INVALID_ISR_STATE);
|
---|
327 |
|
---|
328 | //
|
---|
329 | // Note: We don't ASSERT here, because there are some
|
---|
330 | // machines (e.g., Compaq 386/25) that send back an
|
---|
331 | // extra ACK in response to the SETLED sequence. We've
|
---|
332 | // noticed this when, for example, CAPSLOCK is pressed
|
---|
333 | // at the same time as a normal key. Just ignore
|
---|
334 | // random ACKs.
|
---|
335 | //
|
---|
336 | }
|
---|
337 |
|
---|
338 | break;
|
---|
339 |
|
---|
340 | //
|
---|
341 | // Assume we've got a real, live scan code (or perhaps a keyboard
|
---|
342 | // overrun code, which we treat like a scan code). I.e., a key
|
---|
343 | // has been pressed or released. Queue the ISR DPC to process
|
---|
344 | // a complete scan code sequence.
|
---|
345 | //
|
---|
346 |
|
---|
347 | ScanCodeCase:
|
---|
348 | default:
|
---|
349 |
|
---|
350 | I8xPrint((
|
---|
351 | 3,
|
---|
352 | "I8042PRT-I8042KeyboardInterruptService: real scan code\n"
|
---|
353 | ));
|
---|
354 |
|
---|
355 | //
|
---|
356 | // Differentiate between an extended key sequence (first
|
---|
357 | // byte is E0, followed by a normal make or break byte), or
|
---|
358 | // a normal make code (one byte, the high bit is NOT set),
|
---|
359 | // or a normal break code (one byte, same as the make code
|
---|
360 | // but the high bit is set), or the key #126 byte sequence
|
---|
361 | // (requires special handling -- sequence is E11D459DC5).
|
---|
362 | //
|
---|
363 | // If there is a key detection error/overrun, the keyboard
|
---|
364 | // sends an overrun indicator (0xFF in scan code set 1).
|
---|
365 | // Map it to the overrun indicator expected by the Windows
|
---|
366 | // USER Raw Input Thread.
|
---|
367 | //
|
---|
368 |
|
---|
369 | input = &deviceExtension->KeyboardExtension.CurrentInput;
|
---|
370 | scanState = &deviceExtension->KeyboardExtension.CurrentScanState;
|
---|
371 |
|
---|
372 | if (scanCode == (UCHAR) 0xFF) {
|
---|
373 | I8xPrint((
|
---|
374 | 1,
|
---|
375 | "I8042PRT-I8042KeyboardInterruptService: OVERRUN\n"
|
---|
376 | ));
|
---|
377 | input->MakeCode = KEYBOARD_OVERRUN_MAKE_CODE;
|
---|
378 | input->Flags = 0;
|
---|
379 | *scanState = Normal;
|
---|
380 | } else {
|
---|
381 |
|
---|
382 | switch (*scanState) {
|
---|
383 | case Normal:
|
---|
384 | if (scanCode == (UCHAR) 0xE0) {
|
---|
385 | input->Flags |= KEY_E0;
|
---|
386 | *scanState = GotE0;
|
---|
387 | I8xPrint((
|
---|
388 | 3,
|
---|
389 | "I8042PRT-I8042KeyboardInterruptService: change state to GotE0\n"
|
---|
390 | ));
|
---|
391 | break;
|
---|
392 | } else if (scanCode == (UCHAR) 0xE1) {
|
---|
393 | input->Flags |= KEY_E1;
|
---|
394 | *scanState = GotE1;
|
---|
395 | I8xPrint((
|
---|
396 | 3,
|
---|
397 | "I8042PRT-I8042KeyboardInterruptService: change state to GotE1\n"
|
---|
398 | ));
|
---|
399 | break;
|
---|
400 | }
|
---|
401 |
|
---|
402 | //
|
---|
403 | // Fall through to the GotE0/GotE1 case for the rest of the
|
---|
404 | // Normal case.
|
---|
405 | //
|
---|
406 |
|
---|
407 | case GotE0:
|
---|
408 | case GotE1:
|
---|
409 |
|
---|
410 | #if defined(JAPAN) && defined(_X86_)
|
---|
411 | // Fujitsu Sep.08.1994
|
---|
412 | // We want to write debugging information to the file except stop error.
|
---|
413 |
|
---|
414 | if(deviceExtension->Dump1Keys != 0) {
|
---|
415 | LONG Dump1Keys;
|
---|
416 | UCHAR DumpKey,DumpKey2;
|
---|
417 | BOOLEAN onflag;
|
---|
418 | static UCHAR KeyToScanTbl[134] = {
|
---|
419 | 0x00,0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
|
---|
420 | 0x0A,0x0B,0x0C,0x0D,0x7D,0x0E,0x0F,0x10,0x11,0x12,
|
---|
421 | 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x00,
|
---|
422 | 0x3A,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,
|
---|
423 | 0x27,0x28,0x2B,0x1C,0x2A,0x00,0x2C,0x2D,0x2E,0x2F,
|
---|
424 | 0x30,0x31,0x32,0x33,0x34,0x35,0x73,0x36,0x1D,0x00,
|
---|
425 | 0x38,0x39,0xB8,0x00,0x9D,0x00,0x00,0x00,0x00,0x00,
|
---|
426 | 0x00,0x00,0x00,0x00,0x00,0xD2,0xD3,0x00,0x00,0xCB,
|
---|
427 | 0xC7,0xCF,0x00,0xC8,0xD0,0xC9,0xD1,0x00,0x00,0xCD,
|
---|
428 | 0x45,0x47,0x4B,0x4F,0x00,0xB5,0x48,0x4C,0x50,0x52,
|
---|
429 | 0x37,0x49,0x4D,0x51,0x53,0x4A,0x4E,0x00,0x9C,0x00,
|
---|
430 | 0x01,0x00,0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,
|
---|
431 | 0x43,0x44,0x57,0x58,0x00,0x46,0x00,0x00,0x00,0x00,
|
---|
432 | 0x00,0x7B,0x79,0x70 };
|
---|
433 |
|
---|
434 | Dump1Keys = deviceExtension->Dump1Keys;
|
---|
435 | switch(deviceExtension->Dump2Key) {
|
---|
436 | case 124: // 'Print Screen'
|
---|
437 | DumpKey = 0xB7;
|
---|
438 | DumpKey2 = 0x54;
|
---|
439 | break;
|
---|
440 | default:
|
---|
441 | if(deviceExtension->Dump2Key <= 133)
|
---|
442 | DumpKey = KeyToScanTbl[deviceExtension->Dump2Key];
|
---|
443 | else
|
---|
444 | DumpKey = 0;
|
---|
445 | DumpKey2 = 0;
|
---|
446 | break;
|
---|
447 | }
|
---|
448 | if(scanCode <= (UCHAR) 0x7F) {
|
---|
449 | //
|
---|
450 | // make code
|
---|
451 | //
|
---|
452 | switch(scanCode) {
|
---|
453 | case 0x1D: // 'CTRL'
|
---|
454 | if(*scanState == Normal) // Left
|
---|
455 | deviceExtension->DumpFlags |= 0x20;
|
---|
456 | else if(*scanState == GotE0) // Right
|
---|
457 | deviceExtension->DumpFlags |= 0x02;
|
---|
458 | break;
|
---|
459 | case 0x38: // 'ALT'
|
---|
460 | if(*scanState == Normal) // Left
|
---|
461 | deviceExtension->DumpFlags |= 0x40;
|
---|
462 | else if(*scanState == GotE0) // Right
|
---|
463 | deviceExtension->DumpFlags |= 0x04;
|
---|
464 | break;
|
---|
465 | case 0x36: // Right 'Shift'
|
---|
466 | if(*scanState == Normal)
|
---|
467 | deviceExtension->DumpFlags |= 0x01;
|
---|
468 | break;
|
---|
469 | case 0x2A: // Left 'Shift'
|
---|
470 | if(*scanState == Normal)
|
---|
471 | deviceExtension->DumpFlags |= 0x10;
|
---|
472 | break;
|
---|
473 | default:
|
---|
474 | if((DumpKey & 0x80) == 0) {
|
---|
475 | if(*scanState == Normal
|
---|
476 | && DumpKey == scanCode)
|
---|
477 | break;
|
---|
478 | }
|
---|
479 | else {
|
---|
480 | if(*scanState == GotE0
|
---|
481 | && (DumpKey & 0x7F) == scanCode)
|
---|
482 | break;
|
---|
483 | }
|
---|
484 | if((DumpKey2 & 0x80) == 0) {
|
---|
485 | if(*scanState == Normal
|
---|
486 | && DumpKey2 == scanCode)
|
---|
487 | break;
|
---|
488 | }
|
---|
489 | else {
|
---|
490 | if(*scanState == GotE0
|
---|
491 | && (DumpKey2 & 0x7F) == scanCode)
|
---|
492 | break;
|
---|
493 | }
|
---|
494 | deviceExtension->DumpFlags = 0;
|
---|
495 | break;
|
---|
496 | }
|
---|
497 | }
|
---|
498 | else {
|
---|
499 | //
|
---|
500 | // break code
|
---|
501 | //
|
---|
502 | switch(scanCode & 0x7F) {
|
---|
503 | case 0x1D: // 'CTRL'
|
---|
504 | if(*scanState == Normal) // Left
|
---|
505 | deviceExtension->DumpFlags &= ~0x320;
|
---|
506 | else if(*scanState == GotE0) // Right
|
---|
507 | deviceExtension->DumpFlags &= ~0x302;
|
---|
508 | break;
|
---|
509 | case 0x38: // 'ALT'
|
---|
510 | if(*scanState == Normal) // Left
|
---|
511 | deviceExtension->DumpFlags &= ~0x340;
|
---|
512 | else if(*scanState == GotE0) // Right
|
---|
513 | deviceExtension->DumpFlags &= ~0x304;
|
---|
514 | break;
|
---|
515 | case 0x36: // Right 'Shift'
|
---|
516 | if(*scanState == Normal)
|
---|
517 | deviceExtension->DumpFlags &= ~0x301;
|
---|
518 | break;
|
---|
519 | case 0x2A: // Left 'Shift'
|
---|
520 | if(*scanState == Normal)
|
---|
521 | deviceExtension->DumpFlags &= ~0x310;
|
---|
522 | break;
|
---|
523 | default:
|
---|
524 | onflag = 0;
|
---|
525 | if((DumpKey & 0x80) == 0) {
|
---|
526 | if(*scanState == Normal
|
---|
527 | && DumpKey == (scanCode & 0x7F))
|
---|
528 | onflag = 1;
|
---|
529 | }
|
---|
530 | else {
|
---|
531 | if(*scanState == GotE0
|
---|
532 | && DumpKey == scanCode)
|
---|
533 | onflag = 1;
|
---|
534 | }
|
---|
535 | if((DumpKey2 & 0x80) == 0) {
|
---|
536 | if(*scanState == Normal
|
---|
537 | && DumpKey2 == (scanCode & 0x7F))
|
---|
538 | onflag = 1;
|
---|
539 | }
|
---|
540 | else {
|
---|
541 | if(*scanState == GotE0
|
---|
542 | && DumpKey2 == scanCode)
|
---|
543 | onflag = 1;
|
---|
544 | }
|
---|
545 | if(onflag) {
|
---|
546 | if((deviceExtension->DumpFlags & Dump1Keys) != Dump1Keys)
|
---|
547 | break;
|
---|
548 | if(deviceExtension->DumpFlags & 0x100)
|
---|
549 | deviceExtension->DumpFlags |= 0x200;
|
---|
550 | else
|
---|
551 | deviceExtension->DumpFlags |= 0x100;
|
---|
552 | break;
|
---|
553 | }
|
---|
554 | deviceExtension->DumpFlags = 0;
|
---|
555 | break;
|
---|
556 | }
|
---|
557 | }
|
---|
558 | Dump1Keys |= 0x300;
|
---|
559 | if(deviceExtension->DumpFlags == Dump1Keys) {
|
---|
560 | deviceExtension->DumpFlags = 0;
|
---|
561 | KeBugCheckEx(0x0000FFFF,0,0,0,0);
|
---|
562 | // make occurred blue screen
|
---|
563 | }
|
---|
564 | }
|
---|
565 | #endif
|
---|
566 |
|
---|
567 | if (scanCode > 0x7F) {
|
---|
568 |
|
---|
569 | //
|
---|
570 | // Got a break code. Strip the high bit off
|
---|
571 | // to get the associated make code and set flags
|
---|
572 | // to indicate a break code.
|
---|
573 | //
|
---|
574 |
|
---|
575 | I8xPrint((
|
---|
576 | 3,
|
---|
577 | "I8042PRT-I8042KeyboardInterruptService: BREAK code\n"
|
---|
578 | ));
|
---|
579 |
|
---|
580 | input->MakeCode = scanCode & 0x7F;
|
---|
581 | input->Flags |= KEY_BREAK;
|
---|
582 |
|
---|
583 | } else {
|
---|
584 |
|
---|
585 | //
|
---|
586 | // Got a make code.
|
---|
587 | //
|
---|
588 |
|
---|
589 | I8xPrint((
|
---|
590 | 3,
|
---|
591 | "I8042PRT-I8042KeyboardInterruptService: MAKE code\n"
|
---|
592 | ));
|
---|
593 |
|
---|
594 | input->MakeCode = scanCode;
|
---|
595 |
|
---|
596 | //
|
---|
597 | // If the input scan code is debug stop, then drop
|
---|
598 | // into the kernel debugger if it is active.
|
---|
599 | //
|
---|
600 |
|
---|
601 | if (*((PBOOLEAN)(*(PLONG)&KdDebuggerNotPresent))
|
---|
602 | == FALSE && !(input->Flags & KEY_BREAK)) {
|
---|
603 | if (ENHANCED_KEYBOARD(
|
---|
604 | deviceExtension->Configuration.KeyboardAttributes.KeyboardIdentifier
|
---|
605 | )) {
|
---|
606 | //
|
---|
607 | // Enhanced 101 keyboard, SysReq key is 0xE0 0x37.
|
---|
608 | //
|
---|
609 |
|
---|
610 | if ((input->MakeCode == KEYBOARD_DEBUG_HOTKEY_ENH) &&
|
---|
611 | (input->Flags & KEY_E0)) {
|
---|
612 | __try {
|
---|
613 | if (**((PUCHAR *)&KdDebuggerEnabled) != FALSE) {
|
---|
614 | DbgBreakPointWithStatus(DBG_STATUS_SYSRQ);
|
---|
615 | }
|
---|
616 |
|
---|
617 | } __except(EXCEPTION_EXECUTE_HANDLER) {
|
---|
618 | }
|
---|
619 | }
|
---|
620 | //
|
---|
621 | // 84-key AT keyboard, SysReq key is 0xE0 0x54.
|
---|
622 | //
|
---|
623 |
|
---|
624 | } else if ((input->MakeCode == KEYBOARD_DEBUG_HOTKEY_AT)) {
|
---|
625 | __try {
|
---|
626 | if (**((PUCHAR *)&KdDebuggerEnabled) != FALSE) {
|
---|
627 | DbgBreakPointWithStatus(DBG_STATUS_SYSRQ);
|
---|
628 | }
|
---|
629 |
|
---|
630 | } __except(EXCEPTION_EXECUTE_HANDLER) {
|
---|
631 | }
|
---|
632 | }
|
---|
633 | }
|
---|
634 | }
|
---|
635 |
|
---|
636 | //
|
---|
637 | // Reset the state to Normal.
|
---|
638 | //
|
---|
639 |
|
---|
640 | *scanState = Normal;
|
---|
641 | break;
|
---|
642 |
|
---|
643 | default:
|
---|
644 |
|
---|
645 | //
|
---|
646 | // Queue a DPC to log an internal driver error.
|
---|
647 | //
|
---|
648 |
|
---|
649 | KeInsertQueueDpc(
|
---|
650 | &deviceExtension->ErrorLogDpc,
|
---|
651 | (PIRP) NULL,
|
---|
652 | (PVOID) (ULONG) I8042_INVALID_ISR_STATE);
|
---|
653 |
|
---|
654 | ASSERT(FALSE);
|
---|
655 | break;
|
---|
656 | }
|
---|
657 | }
|
---|
658 |
|
---|
659 | //
|
---|
660 | // In the Normal state, if the keyboard device is enabled,
|
---|
661 | // add the data to the InputData queue and queue the ISR DPC.
|
---|
662 | //
|
---|
663 |
|
---|
664 | if (*scanState == Normal) {
|
---|
665 |
|
---|
666 | if (deviceExtension->KeyboardEnableCount) {
|
---|
667 | deviceExtension->KeyboardExtension.CurrentInput.UnitId =
|
---|
668 | deviceExtension->KeyboardExtension.UnitId;
|
---|
669 | if (!I8xWriteDataToKeyboardQueue(
|
---|
670 | &deviceExtension->KeyboardExtension,
|
---|
671 | input
|
---|
672 | )) {
|
---|
673 |
|
---|
674 | //
|
---|
675 | // The InputData queue overflowed. There is
|
---|
676 | // not much that can be done about it, so just
|
---|
677 | // continue (but don't queue the ISR DPC, since
|
---|
678 | // no new packets were added to the queue).
|
---|
679 | //
|
---|
680 | // Queue a DPC to log an overrun error.
|
---|
681 | //
|
---|
682 |
|
---|
683 | I8xPrint((
|
---|
684 | 1,
|
---|
685 | "I8042PRT-I8042KeyboardInterruptService: queue overflow\n"
|
---|
686 | ));
|
---|
687 |
|
---|
688 | if (deviceExtension->KeyboardExtension.OkayToLogOverflow) {
|
---|
689 | KeInsertQueueDpc(
|
---|
690 | &deviceExtension->ErrorLogDpc,
|
---|
691 | (PIRP) NULL,
|
---|
692 | (PVOID) (ULONG) I8042_KBD_BUFFER_OVERFLOW
|
---|
693 | );
|
---|
694 | deviceExtension->KeyboardExtension.OkayToLogOverflow = FALSE;
|
---|
695 | }
|
---|
696 |
|
---|
697 | } else if (deviceExtension->DpcInterlockKeyboard >= 0) {
|
---|
698 |
|
---|
699 | //
|
---|
700 | // The ISR DPC is already executing. Tell the ISR DPC
|
---|
701 | // it has more work to do by incrementing
|
---|
702 | // DpcInterlockKeyboard.
|
---|
703 | //
|
---|
704 |
|
---|
705 | deviceExtension->DpcInterlockKeyboard += 1;
|
---|
706 |
|
---|
707 | } else {
|
---|
708 |
|
---|
709 | //
|
---|
710 | // Queue the ISR DPC.
|
---|
711 | //
|
---|
712 |
|
---|
713 | KeInsertQueueDpc(
|
---|
714 | &deviceExtension->KeyboardIsrDpc,
|
---|
715 | deviceObject->CurrentIrp,
|
---|
716 | NULL
|
---|
717 | );
|
---|
718 | }
|
---|
719 | }
|
---|
720 |
|
---|
721 | //
|
---|
722 | // Reset the input state.
|
---|
723 | //
|
---|
724 |
|
---|
725 | input->Flags = 0;
|
---|
726 | }
|
---|
727 |
|
---|
728 | break;
|
---|
729 |
|
---|
730 | }
|
---|
731 |
|
---|
732 | I8xPrint((2, "I8042PRT-I8042KeyboardInterruptService: exit\n"));
|
---|
733 |
|
---|
734 | return(TRUE);
|
---|
735 | }
|
---|
736 | |
---|
737 |
|
---|
738 | //
|
---|
739 | // The following table is used to convert typematic rate (keys per
|
---|
740 | // second) into the value expected by the keyboard. The index into the
|
---|
741 | // array is the number of keys per second. The resulting value is
|
---|
742 | // the bit equate to send to the keyboard.
|
---|
743 | //
|
---|
744 |
|
---|
745 | UCHAR TypematicPeriod[] = {
|
---|
746 | 31, // 0 keys per second
|
---|
747 | 31, // 1 keys per second
|
---|
748 | 28, // 2 keys per second, This is really 2.5, needed for NEXUS.
|
---|
749 | 26, // 3 keys per second
|
---|
750 | 23, // 4 keys per second
|
---|
751 | 20, // 5 keys per second
|
---|
752 | 18, // 6 keys per second
|
---|
753 | 17, // 7 keys per second
|
---|
754 | 15, // 8 keys per second
|
---|
755 | 13, // 9 keys per second
|
---|
756 | 12, // 10 keys per second
|
---|
757 | 11, // 11 keys per second
|
---|
758 | 10, // 12 keys per second
|
---|
759 | 9, // 13 keys per second
|
---|
760 | 9, // 14 keys per second
|
---|
761 | 8, // 15 keys per second
|
---|
762 | 7, // 16 keys per second
|
---|
763 | 6, // 17 keys per second
|
---|
764 | 5, // 18 keys per second
|
---|
765 | 4, // 19 keys per second
|
---|
766 | 4, // 20 keys per second
|
---|
767 | 3, // 21 keys per second
|
---|
768 | 3, // 22 keys per second
|
---|
769 | 2, // 23 keys per second
|
---|
770 | 2, // 24 keys per second
|
---|
771 | 1, // 25 keys per second
|
---|
772 | 1, // 26 keys per second
|
---|
773 | 1 // 27 keys per second
|
---|
774 | // > 27 keys per second, use 0
|
---|
775 | };
|
---|
776 |
|
---|
777 | UCHAR
|
---|
778 | I8xConvertTypematicParameters(
|
---|
779 | IN USHORT Rate,
|
---|
780 | IN USHORT Delay
|
---|
781 | )
|
---|
782 |
|
---|
783 | /*++
|
---|
784 |
|
---|
785 | Routine Description:
|
---|
786 |
|
---|
787 | This routine converts the typematic rate and delay to the form the
|
---|
788 | keyboard expects.
|
---|
789 |
|
---|
790 | The byte passed to the keyboard looks like this:
|
---|
791 |
|
---|
792 | - bit 7 is zero
|
---|
793 | - bits 5 and 6 indicate the delay
|
---|
794 | - bits 0-4 indicate the rate
|
---|
795 |
|
---|
796 | The delay is equal to 1 plus the binary value of bits 6 and 5,
|
---|
797 | multiplied by 250 milliseconds.
|
---|
798 |
|
---|
799 | The period (interval from one typematic output to the next) is
|
---|
800 | determined by the following equation:
|
---|
801 |
|
---|
802 | Period = (8 + A) x (2^B) x 0.00417 seconds
|
---|
803 | where
|
---|
804 | A = binary value of bits 0-2
|
---|
805 | B = binary value of bits 3 and 4
|
---|
806 |
|
---|
807 |
|
---|
808 | Arguments:
|
---|
809 |
|
---|
810 | Rate - Number of keys per second.
|
---|
811 |
|
---|
812 | Delay - Number of milliseconds to delay before the key repeat starts.
|
---|
813 |
|
---|
814 | Return Value:
|
---|
815 |
|
---|
816 | The byte to pass to the keyboard.
|
---|
817 |
|
---|
818 | --*/
|
---|
819 |
|
---|
820 | {
|
---|
821 | UCHAR value;
|
---|
822 |
|
---|
823 | I8xPrint((2, "I8042PRT-I8xConvertTypematicParameters: enter\n"));
|
---|
824 |
|
---|
825 | //
|
---|
826 | // Calculate the delay bits.
|
---|
827 | //
|
---|
828 |
|
---|
829 | value = (UCHAR) ((Delay / 250) - 1);
|
---|
830 |
|
---|
831 | //
|
---|
832 | // Put delay bits in the right place.
|
---|
833 | //
|
---|
834 |
|
---|
835 | value <<= 5;
|
---|
836 |
|
---|
837 | //
|
---|
838 | // Get the typematic period from the table. If keys per second
|
---|
839 | // is > 27, the typematic period value is zero.
|
---|
840 | //
|
---|
841 |
|
---|
842 | if (Rate <= 27) {
|
---|
843 | value |= TypematicPeriod[Rate];
|
---|
844 | }
|
---|
845 |
|
---|
846 | I8xPrint((2, "I8042PRT-I8xConvertTypematicParameters: exit\n"));
|
---|
847 |
|
---|
848 | return(value);
|
---|
849 | }
|
---|
850 | |
---|
851 |
|
---|
852 | NTSTATUS
|
---|
853 | I8xInitializeKeyboard(
|
---|
854 | IN PDEVICE_OBJECT DeviceObject
|
---|
855 | )
|
---|
856 |
|
---|
857 | /*++
|
---|
858 |
|
---|
859 | Routine Description:
|
---|
860 |
|
---|
861 | This routine initializes the i8042 keyboard hardware. It is called
|
---|
862 | only at initialization, and does not synchronize access to the hardware.
|
---|
863 |
|
---|
864 | Arguments:
|
---|
865 |
|
---|
866 | DeviceObject - Pointer to the device object.
|
---|
867 |
|
---|
868 | Return Value:
|
---|
869 |
|
---|
870 | Returns status.
|
---|
871 |
|
---|
872 | --*/
|
---|
873 |
|
---|
874 | {
|
---|
875 | NTSTATUS status;
|
---|
876 | PKEYBOARD_ID id;
|
---|
877 | PDEVICE_EXTENSION deviceExtension;
|
---|
878 | UCHAR byte;
|
---|
879 | I8042_TRANSMIT_CCB_CONTEXT transmitCCBContext;
|
---|
880 | ULONG i;
|
---|
881 | PIO_ERROR_LOG_PACKET errorLogEntry;
|
---|
882 | ULONG uniqueErrorValue;
|
---|
883 | NTSTATUS errorCode = STATUS_SUCCESS;
|
---|
884 | ULONG dumpCount;
|
---|
885 | #if !(defined(_X86_) || defined(_PPC_)) // IBMCPK: MIPS specific initialization
|
---|
886 | PI8042_CONFIGURATION_INFORMATION configuration;
|
---|
887 | PKEYBOARD_ID keyboardId;
|
---|
888 | #endif
|
---|
889 | LARGE_INTEGER startOfSpin, nextQuery, difference, tenSeconds;
|
---|
890 | BOOLEAN waitForAckOnReset = WAIT_FOR_ACKNOWLEDGE;
|
---|
891 |
|
---|
892 | #define DUMP_COUNT 4
|
---|
893 | ULONG dumpData[DUMP_COUNT];
|
---|
894 |
|
---|
895 | I8xPrint((2, "I8042PRT-I8xInitializeKeyboard: enter\n"));
|
---|
896 |
|
---|
897 | for (i = 0; i < DUMP_COUNT; i++)
|
---|
898 | dumpData[i] = 0;
|
---|
899 |
|
---|
900 | //
|
---|
901 | // Get the device extension.
|
---|
902 | //
|
---|
903 |
|
---|
904 | deviceExtension = DeviceObject->DeviceExtension;
|
---|
905 |
|
---|
906 | //
|
---|
907 | // Reset the keyboard.
|
---|
908 | //
|
---|
909 |
|
---|
910 | StartOfReset:
|
---|
911 | status = I8xPutBytePolled(
|
---|
912 | (CCHAR) DataPort,
|
---|
913 | waitForAckOnReset,
|
---|
914 | (CCHAR) KeyboardDeviceType,
|
---|
915 | deviceExtension,
|
---|
916 | (UCHAR) KEYBOARD_RESET
|
---|
917 | );
|
---|
918 | if (!NT_SUCCESS(status)) {
|
---|
919 | I8xPrint((
|
---|
920 | 1,
|
---|
921 | "I8042PRT-I8xInitializeKeyboard: failed keyboard reset, status 0x%x\n",
|
---|
922 | status
|
---|
923 | ));
|
---|
924 |
|
---|
925 | //
|
---|
926 | // Set up error log info.
|
---|
927 | //
|
---|
928 |
|
---|
929 | errorCode = I8042_KBD_RESET_COMMAND_FAILED;
|
---|
930 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 510;
|
---|
931 | dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
|
---|
932 | dumpData[1] = DataPort;
|
---|
933 | dumpData[2] = KEYBOARD_RESET;
|
---|
934 | dumpCount = 3;
|
---|
935 |
|
---|
936 | //
|
---|
937 | // NOTE: The following line was commented out to work around a
|
---|
938 | // problem with the Gateway 4DX2/66V when an old Compaq 286
|
---|
939 | // keyboard is attached. In this case, the keyboard reset
|
---|
940 | // is not acknowledged (at least, the system never
|
---|
941 | // receives the ack). Instead, the KEYBOARD_COMPLETE_SUCCESS
|
---|
942 | // byte is sitting in the i8042 output buffer. The workaround
|
---|
943 | // is to ignore the keyboard reset failure and continue.
|
---|
944 | //
|
---|
945 | // goto I8xInitializeKeyboardExit;
|
---|
946 | }
|
---|
947 |
|
---|
948 | //
|
---|
949 | // Get the keyboard reset self-test response. A response byte of
|
---|
950 | // KEYBOARD_COMPLETE_SUCCESS indicates success; KEYBOARD_COMPLETE_FAILURE
|
---|
951 | // indicates failure.
|
---|
952 | //
|
---|
953 | // Note that it is usually necessary to stall a long time to get the
|
---|
954 | // keyboard reset/self-test to work. The stall value was determined by
|
---|
955 | // experimentation.
|
---|
956 | //
|
---|
957 |
|
---|
958 | KeQueryTickCount(&startOfSpin);
|
---|
959 | for (i = 0; i < 11200; i++) {
|
---|
960 |
|
---|
961 | status = I8xGetBytePolled(
|
---|
962 | (CCHAR) KeyboardDeviceType,
|
---|
963 | deviceExtension,
|
---|
964 | &byte
|
---|
965 | );
|
---|
966 |
|
---|
967 | if (NT_SUCCESS(status)) {
|
---|
968 | if (byte == (UCHAR) KEYBOARD_COMPLETE_SUCCESS) {
|
---|
969 |
|
---|
970 | //
|
---|
971 | // The reset completed successfully.
|
---|
972 | //
|
---|
973 |
|
---|
974 | break;
|
---|
975 |
|
---|
976 | } else {
|
---|
977 |
|
---|
978 | //
|
---|
979 | // There was some sort of failure during the reset
|
---|
980 | // self-test. Continue anyway.
|
---|
981 | //
|
---|
982 |
|
---|
983 | //
|
---|
984 | // Log a warning.
|
---|
985 | //
|
---|
986 |
|
---|
987 |
|
---|
988 | dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
|
---|
989 | dumpData[1] = KeyboardDeviceType;
|
---|
990 | dumpData[2] = KEYBOARD_COMPLETE_SUCCESS;
|
---|
991 | dumpData[3] = byte;
|
---|
992 |
|
---|
993 | I8xLogError(
|
---|
994 | DeviceObject,
|
---|
995 | I8042_KBD_RESET_RESPONSE_FAILED,
|
---|
996 | I8042_ERROR_VALUE_BASE + 515,
|
---|
997 | status,
|
---|
998 | dumpData,
|
---|
999 | 4
|
---|
1000 | );
|
---|
1001 |
|
---|
1002 | break;
|
---|
1003 | }
|
---|
1004 |
|
---|
1005 |
|
---|
1006 | } else {
|
---|
1007 |
|
---|
1008 | if (status == STATUS_IO_TIMEOUT) {
|
---|
1009 |
|
---|
1010 | //
|
---|
1011 | // Stall, and then try again to get a response from
|
---|
1012 | // the reset.
|
---|
1013 | //
|
---|
1014 |
|
---|
1015 | KeStallExecutionProcessor(50);
|
---|
1016 |
|
---|
1017 | KeQueryTickCount(&nextQuery);
|
---|
1018 |
|
---|
1019 | difference.QuadPart = nextQuery.QuadPart - startOfSpin.QuadPart;
|
---|
1020 | tenSeconds.QuadPart = 10*10*1000*1000;
|
---|
1021 |
|
---|
1022 | ASSERT(KeQueryTimeIncrement() <= MAXLONG);
|
---|
1023 | if (difference.QuadPart*KeQueryTimeIncrement() >=
|
---|
1024 | tenSeconds.QuadPart) {
|
---|
1025 |
|
---|
1026 | break;
|
---|
1027 | }
|
---|
1028 |
|
---|
1029 | } else {
|
---|
1030 |
|
---|
1031 | break;
|
---|
1032 |
|
---|
1033 | }
|
---|
1034 |
|
---|
1035 | }
|
---|
1036 | }
|
---|
1037 |
|
---|
1038 | if (!NT_SUCCESS(status)) {
|
---|
1039 |
|
---|
1040 | if (waitForAckOnReset == WAIT_FOR_ACKNOWLEDGE) {
|
---|
1041 | waitForAckOnReset = NO_WAIT_FOR_ACKNOWLEDGE;
|
---|
1042 | goto StartOfReset;
|
---|
1043 | }
|
---|
1044 |
|
---|
1045 | I8xPrint((
|
---|
1046 | 1,
|
---|
1047 | "I8042PRT-I8xInitializeKeyboard: failed reset response, status 0x%x, byte 0x%x\n",
|
---|
1048 | status,
|
---|
1049 | byte
|
---|
1050 | ));
|
---|
1051 |
|
---|
1052 | //
|
---|
1053 | // Set up error log info.
|
---|
1054 | //
|
---|
1055 |
|
---|
1056 | errorCode = I8042_KBD_RESET_RESPONSE_FAILED;
|
---|
1057 | uniqueErrorValue = I8042_ERROR_VALUE_BASE + 520;
|
---|
1058 | dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
|
---|
1059 | dumpData[1] = KeyboardDeviceType;
|
---|
1060 | dumpData[2] = KEYBOARD_COMPLETE_SUCCESS;
|
---|
1061 | dumpData[3] = byte;
|
---|
1062 | dumpCount = 4;
|
---|
1063 |
|
---|
1064 | goto I8xInitializeKeyboardExit;
|
---|
1065 | }
|
---|
1066 |
|
---|
1067 | //
|
---|
1068 | // Turn off Keyboard Translate Mode. Call I8xTransmitControllerCommand
|
---|
1069 | // to read the Controller Command Byte, modify the appropriate bits, and
|
---|
1070 | // rewrite the Controller Command Byte.
|
---|
1071 | //
|
---|
1072 |
|
---|
1073 | transmitCCBContext.HardwareDisableEnableMask = 0;
|
---|
1074 | transmitCCBContext.AndOperation = AND_OPERATION;
|
---|
1075 | transmitCCBContext.ByteMask = (UCHAR) ~((UCHAR)CCB_KEYBOARD_TRANSLATE_MODE);
|
---|
1076 |
|
---|
1077 | I8xTransmitControllerCommand(
|
---|
1078 | deviceExtension,
|
---|
1079 | (PVOID) &transmitCCBContext
|
---|
1080 | );
|
---|
1081 |
|
---|
1082 | if (!NT_SUCCESS(transmitCCBContext.Status)) {
|
---|
1083 | //
|
---|
1084 | // If failure then retry once. This is for Toshiba T3400CT.
|
---|
1085 | //
|
---|
1086 | I8xTransmitControllerCommand(
|
---|
1087 | deviceExtension,
|
---|
1088 | (PVOID) &transmitCCBContext
|
---|
1089 | );
|
---|
1090 | }
|
---|
1091 |
|
---|
1092 | if (!NT_SUCCESS(transmitCCBContext.Status)) {
|
---|
1093 | I8xPrint((
|
---|
1094 | 1,
|
---|
1095 | "I8042PRT-I8xInitializeKeyboard: could not turn off translate\n"
|
---|
1096 | ));
|
---|
1097 | status = transmitCCBContext.Status;
|
---|
1098 | goto I8xInitializeKeyboardExit;
|
---|
1099 | }
|
---|
1100 |
|
---|
1101 | //
|
---|
1102 | // Get a pointer to the keyboard identifier field.
|
---|
1103 | //
|
---|
1104 |
|
---|
1105 | id = &deviceExtension->Configuration.KeyboardAttributes.KeyboardIdentifier;
|
---|
1106 |
|
---|
1107 | //
|
---|
1108 | // Set the typematic rate and delay. Send the Set Typematic Rate command
|
---|
1109 | // to the keyboard, followed by the typematic rate/delay parameter byte.
|
---|
1110 | // Note that it is often necessary to stall a long time to get this
|
---|
1111 | // to work. The stall value was determined by experimentation. Some
|
---|
1112 | // broken hardware does not accept this command, so ignore errors in the
|
---|
1113 | // hope that the keyboard will work okay anyway.
|
---|
1114 | //
|
---|
1115 | //
|
---|
1116 |
|
---|
1117 | if ((status = I8xPutBytePolled(
|
---|
1118 | (CCHAR) DataPort,
|
---|
1119 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1120 | (CCHAR) KeyboardDeviceType,
|
---|
1121 | deviceExtension,
|
---|
1122 | (UCHAR) SET_KEYBOARD_TYPEMATIC
|
---|
1123 | )) != STATUS_SUCCESS) {
|
---|
1124 | I8xPrint((
|
---|
1125 | 1,
|
---|
1126 | "I8042PRT-I8xInitializeKeyboard: could not send SET TYPEMATIC cmd\n"
|
---|
1127 | ));
|
---|
1128 |
|
---|
1129 | //
|
---|
1130 | // Log an error.
|
---|
1131 | //
|
---|
1132 |
|
---|
1133 | dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
|
---|
1134 | dumpData[1] = DataPort;
|
---|
1135 | dumpData[2] = SET_KEYBOARD_TYPEMATIC;
|
---|
1136 |
|
---|
1137 | I8xLogError(
|
---|
1138 | DeviceObject,
|
---|
1139 | I8042_SET_TYPEMATIC_FAILED,
|
---|
1140 | I8042_ERROR_VALUE_BASE + 535,
|
---|
1141 | status,
|
---|
1142 | dumpData,
|
---|
1143 | 3
|
---|
1144 | );
|
---|
1145 |
|
---|
1146 | } else if ((status = I8xPutBytePolled(
|
---|
1147 | (CCHAR) DataPort,
|
---|
1148 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1149 | (CCHAR) KeyboardDeviceType,
|
---|
1150 | deviceExtension,
|
---|
1151 | I8xConvertTypematicParameters(
|
---|
1152 | deviceExtension->Configuration.KeyRepeatCurrent.Rate,
|
---|
1153 | deviceExtension->Configuration.KeyRepeatCurrent.Delay
|
---|
1154 | ))) != STATUS_SUCCESS) {
|
---|
1155 | I8xPrint((
|
---|
1156 | 1,
|
---|
1157 | "I8042PRT-I8xInitializeKeyboard: could not send typematic param\n"
|
---|
1158 | ));
|
---|
1159 |
|
---|
1160 | //
|
---|
1161 | // Log an error.
|
---|
1162 | //
|
---|
1163 |
|
---|
1164 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1165 | dumpData[1] = DataPort;
|
---|
1166 | dumpData[2] = SET_KEYBOARD_TYPEMATIC;
|
---|
1167 | dumpData[3] =
|
---|
1168 | I8xConvertTypematicParameters(
|
---|
1169 | deviceExtension->Configuration.KeyRepeatCurrent.Rate,
|
---|
1170 | deviceExtension->Configuration.KeyRepeatCurrent.Delay
|
---|
1171 | );
|
---|
1172 |
|
---|
1173 | I8xLogError(
|
---|
1174 | DeviceObject,
|
---|
1175 | I8042_SET_TYPEMATIC_FAILED,
|
---|
1176 | I8042_ERROR_VALUE_BASE + 540,
|
---|
1177 | status,
|
---|
1178 | dumpData,
|
---|
1179 | 4
|
---|
1180 | );
|
---|
1181 |
|
---|
1182 | }
|
---|
1183 |
|
---|
1184 | status = STATUS_SUCCESS;
|
---|
1185 |
|
---|
1186 | //
|
---|
1187 | // Set the keyboard indicator lights. Ignore errors.
|
---|
1188 | //
|
---|
1189 |
|
---|
1190 | if ((status = I8xPutBytePolled(
|
---|
1191 | (CCHAR) DataPort,
|
---|
1192 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1193 | (CCHAR) KeyboardDeviceType,
|
---|
1194 | deviceExtension,
|
---|
1195 | (UCHAR) SET_KEYBOARD_INDICATORS
|
---|
1196 | )) != STATUS_SUCCESS) {
|
---|
1197 | I8xPrint((
|
---|
1198 | 1,
|
---|
1199 | "I8042PRT-I8xInitializeKeyboard: could not send SET LEDS cmd\n"
|
---|
1200 | ));
|
---|
1201 |
|
---|
1202 | //
|
---|
1203 | // Log an error.
|
---|
1204 | //
|
---|
1205 |
|
---|
1206 | dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
|
---|
1207 | dumpData[1] = DataPort;
|
---|
1208 | dumpData[2] = SET_KEYBOARD_INDICATORS;
|
---|
1209 |
|
---|
1210 | I8xLogError(
|
---|
1211 | DeviceObject,
|
---|
1212 | I8042_SET_LED_FAILED,
|
---|
1213 | I8042_ERROR_VALUE_BASE + 545,
|
---|
1214 | status,
|
---|
1215 | dumpData,
|
---|
1216 | 3
|
---|
1217 | );
|
---|
1218 |
|
---|
1219 | } else if ((status = I8xPutBytePolled(
|
---|
1220 | (CCHAR) DataPort,
|
---|
1221 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1222 | (CCHAR) KeyboardDeviceType,
|
---|
1223 | deviceExtension,
|
---|
1224 | (UCHAR) deviceExtension->Configuration.KeyboardIndicators.LedFlags
|
---|
1225 | )) != STATUS_SUCCESS) {
|
---|
1226 | I8xPrint((
|
---|
1227 | 1,
|
---|
1228 | "I8042PRT-I8xInitializeKeyboard: could not send SET LEDS param\n"
|
---|
1229 | ));
|
---|
1230 |
|
---|
1231 | //
|
---|
1232 | // Log an error.
|
---|
1233 | //
|
---|
1234 |
|
---|
1235 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1236 | dumpData[1] = DataPort;
|
---|
1237 | dumpData[2] = SET_KEYBOARD_INDICATORS;
|
---|
1238 | dumpData[3] =
|
---|
1239 | deviceExtension->Configuration.KeyboardIndicators.LedFlags;
|
---|
1240 |
|
---|
1241 | I8xLogError(
|
---|
1242 | DeviceObject,
|
---|
1243 | I8042_SET_LED_FAILED,
|
---|
1244 | I8042_ERROR_VALUE_BASE + 550,
|
---|
1245 | status,
|
---|
1246 | dumpData,
|
---|
1247 | 4
|
---|
1248 | );
|
---|
1249 |
|
---|
1250 | }
|
---|
1251 |
|
---|
1252 | status = STATUS_SUCCESS;
|
---|
1253 |
|
---|
1254 | #if !(defined(_X86_) || defined(_PPC_)) // IBMCPK: MIPS specific initialization
|
---|
1255 |
|
---|
1256 | //
|
---|
1257 | // NOTE: This code is necessary until the MIPS firmware stops
|
---|
1258 | // selecting scan code set 3. Select scan code set 2 here.
|
---|
1259 | // Since the translate bit is set, the net effect is that
|
---|
1260 | // we will receive scan code set 1 bytes.
|
---|
1261 | //
|
---|
1262 |
|
---|
1263 | if (ENHANCED_KEYBOARD(*id)) {
|
---|
1264 | status = I8xPutBytePolled(
|
---|
1265 | (CCHAR) DataPort,
|
---|
1266 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1267 | (CCHAR) KeyboardDeviceType,
|
---|
1268 | deviceExtension,
|
---|
1269 | (UCHAR) SELECT_SCAN_CODE_SET
|
---|
1270 | );
|
---|
1271 |
|
---|
1272 | if (NT_SUCCESS(status)) {
|
---|
1273 |
|
---|
1274 | //
|
---|
1275 | // Send the associated parameter byte.
|
---|
1276 | //
|
---|
1277 |
|
---|
1278 | status = I8xPutBytePolled(
|
---|
1279 | (CCHAR) DataPort,
|
---|
1280 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1281 | (CCHAR) KeyboardDeviceType,
|
---|
1282 | deviceExtension,
|
---|
1283 | (UCHAR) 2
|
---|
1284 | );
|
---|
1285 | }
|
---|
1286 |
|
---|
1287 | if (!NT_SUCCESS(status)) {
|
---|
1288 | I8xPrint((
|
---|
1289 | 1,
|
---|
1290 | "I8042PRT-I8xInitializeKeyboard: could not send Select Scan command\n"
|
---|
1291 | ));
|
---|
1292 |
|
---|
1293 | //
|
---|
1294 | // This failed so probably what we have here isn't an enhanced
|
---|
1295 | // keyboard at all. Make this an old style keyboard.
|
---|
1296 | //
|
---|
1297 |
|
---|
1298 | configuration = &deviceExtension->Configuration;
|
---|
1299 | keyboardId = &configuration->KeyboardAttributes.KeyboardIdentifier;
|
---|
1300 |
|
---|
1301 | keyboardId->Type = 3;
|
---|
1302 |
|
---|
1303 | configuration->KeyboardAttributes.NumberOfFunctionKeys =
|
---|
1304 | KeyboardTypeInformation[keyboardId->Type - 1].NumberOfFunctionKeys;
|
---|
1305 | configuration->KeyboardAttributes.NumberOfIndicators =
|
---|
1306 | KeyboardTypeInformation[keyboardId->Type - 1].NumberOfIndicators;
|
---|
1307 | configuration->KeyboardAttributes.NumberOfKeysTotal =
|
---|
1308 | KeyboardTypeInformation[keyboardId->Type - 1].NumberOfKeysTotal;
|
---|
1309 |
|
---|
1310 | status = STATUS_SUCCESS;
|
---|
1311 | }
|
---|
1312 | }
|
---|
1313 | #endif
|
---|
1314 | #ifdef JAPAN
|
---|
1315 | // NLS Keyboard Support Code.
|
---|
1316 | if (IBM02_KEYBOARD(*id)) {
|
---|
1317 |
|
---|
1318 | //
|
---|
1319 | // IBM-J 5576-002 Keyboard should set local scan code set for
|
---|
1320 | // supplied NLS key.
|
---|
1321 | //
|
---|
1322 |
|
---|
1323 | status = I8xPutBytePolled(
|
---|
1324 | (CCHAR) DataPort,
|
---|
1325 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1326 | (CCHAR) KeyboardDeviceType,
|
---|
1327 | deviceExtension,
|
---|
1328 | (UCHAR) SELECT_SCAN_CODE_SET
|
---|
1329 | );
|
---|
1330 | if (status != STATUS_SUCCESS) {
|
---|
1331 | I8xPrint((
|
---|
1332 | 1,
|
---|
1333 | "I8042PRT-I8xInitializeKeyboard: could not send Select Scan command\n"
|
---|
1334 | ));
|
---|
1335 | I8xPrint((
|
---|
1336 | 0,
|
---|
1337 | "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 82h\n"
|
---|
1338 | ));
|
---|
1339 | deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 3;
|
---|
1340 | } else {
|
---|
1341 |
|
---|
1342 | //
|
---|
1343 | // Send the associated parameter byte.
|
---|
1344 | //
|
---|
1345 |
|
---|
1346 | status = I8xPutBytePolled(
|
---|
1347 | (CCHAR) DataPort,
|
---|
1348 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1349 | (CCHAR) KeyboardDeviceType,
|
---|
1350 | deviceExtension,
|
---|
1351 | (UCHAR) 0x82
|
---|
1352 | );
|
---|
1353 | if (status != STATUS_SUCCESS) {
|
---|
1354 | I8xPrint((
|
---|
1355 | 1,
|
---|
1356 | "I8042PRT-I8xInitializeKeyboard: could not send Select Scan param\n"
|
---|
1357 | ));
|
---|
1358 | I8xPrint((
|
---|
1359 | 0,
|
---|
1360 | "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 82h\n"
|
---|
1361 | ));
|
---|
1362 | deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 3;
|
---|
1363 | }
|
---|
1364 | }
|
---|
1365 | }
|
---|
1366 | #endif
|
---|
1367 |
|
---|
1368 | if (deviceExtension->Configuration.KeyboardAttributes.KeyboardMode == 1) {
|
---|
1369 |
|
---|
1370 | //
|
---|
1371 | // Turn translate back on. The keyboard should, by default, send
|
---|
1372 | // scan code set 2. When the translate bit in the 8042 command byte
|
---|
1373 | // is on, the 8042 translates the scan code set 2 bytes to scan code
|
---|
1374 | // set 1 before sending them to the CPU. Scan code set 1 is
|
---|
1375 | // the industry standard scan code set.
|
---|
1376 | //
|
---|
1377 | // N.B. It does not appear to be possible to change the translate
|
---|
1378 | // bit on some models of PS/2.
|
---|
1379 | //
|
---|
1380 |
|
---|
1381 | transmitCCBContext.HardwareDisableEnableMask = 0;
|
---|
1382 | transmitCCBContext.AndOperation = OR_OPERATION;
|
---|
1383 | transmitCCBContext.ByteMask = (UCHAR) CCB_KEYBOARD_TRANSLATE_MODE;
|
---|
1384 |
|
---|
1385 | I8xTransmitControllerCommand(
|
---|
1386 | deviceExtension,
|
---|
1387 | (PVOID) &transmitCCBContext
|
---|
1388 | );
|
---|
1389 |
|
---|
1390 | if (!NT_SUCCESS(transmitCCBContext.Status)) {
|
---|
1391 | I8xPrint((
|
---|
1392 | 1,
|
---|
1393 | "I8042PRT-I8xInitializeKeyboard: couldn't turn on translate\n"
|
---|
1394 | ));
|
---|
1395 | if (transmitCCBContext.Status == STATUS_DEVICE_DATA_ERROR) {
|
---|
1396 |
|
---|
1397 | //
|
---|
1398 | // Could not turn translate back on. This happens on some
|
---|
1399 | // PS/2 machines. In this case, select scan code set 1
|
---|
1400 | // for the keyboard, since the 8042 will not do the
|
---|
1401 | // translation from the scan code set 2, which is what the
|
---|
1402 | // KEYBOARD_RESET caused the keyboard to default to.
|
---|
1403 | //
|
---|
1404 |
|
---|
1405 | if (ENHANCED_KEYBOARD(*id)) {
|
---|
1406 | status = I8xPutBytePolled(
|
---|
1407 | (CCHAR) DataPort,
|
---|
1408 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1409 | (CCHAR) KeyboardDeviceType,
|
---|
1410 | deviceExtension,
|
---|
1411 | (UCHAR) SELECT_SCAN_CODE_SET
|
---|
1412 | );
|
---|
1413 | if (!NT_SUCCESS(status)) {
|
---|
1414 | I8xPrint((
|
---|
1415 | 1,
|
---|
1416 | "I8042PRT-I8xInitializeKeyboard: could not send Select Scan command\n"
|
---|
1417 | ));
|
---|
1418 | I8xPrint((
|
---|
1419 | 0,
|
---|
1420 | "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 2\n"
|
---|
1421 | ));
|
---|
1422 | deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 2;
|
---|
1423 | //
|
---|
1424 | // Log an error.
|
---|
1425 | //
|
---|
1426 |
|
---|
1427 | dumpData[0] = KBDMOU_COULD_NOT_SEND_COMMAND;
|
---|
1428 | dumpData[1] = DataPort;
|
---|
1429 | dumpData[2] = SELECT_SCAN_CODE_SET;
|
---|
1430 |
|
---|
1431 | I8xLogError(
|
---|
1432 | DeviceObject,
|
---|
1433 | I8042_SELECT_SCANSET_FAILED,
|
---|
1434 | I8042_ERROR_VALUE_BASE + 555,
|
---|
1435 | status,
|
---|
1436 | dumpData,
|
---|
1437 | 3
|
---|
1438 | );
|
---|
1439 |
|
---|
1440 | } else {
|
---|
1441 |
|
---|
1442 | //
|
---|
1443 | // Send the associated parameter byte.
|
---|
1444 | //
|
---|
1445 |
|
---|
1446 | status = I8xPutBytePolled(
|
---|
1447 | (CCHAR) DataPort,
|
---|
1448 | WAIT_FOR_ACKNOWLEDGE,
|
---|
1449 | (CCHAR) KeyboardDeviceType,
|
---|
1450 | deviceExtension,
|
---|
1451 | #ifdef JAPAN
|
---|
1452 | // NLS Keyboard Support Code.
|
---|
1453 | (UCHAR) (IBM02_KEYBOARD(*id) ? 0x81 : 1 )
|
---|
1454 | #else
|
---|
1455 | (UCHAR) 1
|
---|
1456 | #endif
|
---|
1457 | );
|
---|
1458 | if (!NT_SUCCESS(status)) {
|
---|
1459 | I8xPrint((
|
---|
1460 | 1,
|
---|
1461 | "I8042PRT-I8xInitializeKeyboard: could not send Select Scan param\n"
|
---|
1462 | ));
|
---|
1463 | I8xPrint((
|
---|
1464 | 0,
|
---|
1465 | "I8042PRT-I8xInitializeKeyboard: WARNING - using scan set 2\n"
|
---|
1466 | ));
|
---|
1467 | deviceExtension->Configuration.KeyboardAttributes.KeyboardMode = 2;
|
---|
1468 | //
|
---|
1469 | // Log an error.
|
---|
1470 | //
|
---|
1471 |
|
---|
1472 | dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
|
---|
1473 | dumpData[1] = DataPort;
|
---|
1474 | dumpData[2] = SELECT_SCAN_CODE_SET;
|
---|
1475 | dumpData[3] = 1;
|
---|
1476 |
|
---|
1477 | I8xLogError(
|
---|
1478 | DeviceObject,
|
---|
1479 | I8042_SELECT_SCANSET_FAILED,
|
---|
1480 | I8042_ERROR_VALUE_BASE + 560,
|
---|
1481 | status,
|
---|
1482 | dumpData,
|
---|
1483 | 4
|
---|
1484 | );
|
---|
1485 |
|
---|
1486 | }
|
---|
1487 | }
|
---|
1488 | }
|
---|
1489 |
|
---|
1490 | } else {
|
---|
1491 | status = transmitCCBContext.Status;
|
---|
1492 | goto I8xInitializeKeyboardExit;
|
---|
1493 | }
|
---|
1494 | }
|
---|
1495 | }
|
---|
1496 |
|
---|
1497 | I8xInitializeKeyboardExit:
|
---|
1498 |
|
---|
1499 | //
|
---|
1500 | // If the keyboard initialization failed, log an error.
|
---|
1501 | //
|
---|
1502 |
|
---|
1503 | if (errorCode != STATUS_SUCCESS) {
|
---|
1504 |
|
---|
1505 | errorLogEntry = (PIO_ERROR_LOG_PACKET)
|
---|
1506 | IoAllocateErrorLogEntry(
|
---|
1507 | DeviceObject,
|
---|
1508 | (UCHAR) (sizeof(IO_ERROR_LOG_PACKET)
|
---|
1509 | + (dumpCount * sizeof(ULONG)))
|
---|
1510 | );
|
---|
1511 |
|
---|
1512 | if (errorLogEntry != NULL) {
|
---|
1513 |
|
---|
1514 | errorLogEntry->ErrorCode = errorCode;
|
---|
1515 | errorLogEntry->DumpDataSize = (USHORT) dumpCount * sizeof(ULONG);
|
---|
1516 | errorLogEntry->SequenceNumber = 0;
|
---|
1517 | errorLogEntry->MajorFunctionCode = 0;
|
---|
1518 | errorLogEntry->IoControlCode = 0;
|
---|
1519 | errorLogEntry->RetryCount = 0;
|
---|
1520 | errorLogEntry->UniqueErrorValue = uniqueErrorValue;
|
---|
1521 | errorLogEntry->FinalStatus = status;
|
---|
1522 | for (i = 0; i < dumpCount; i++)
|
---|
1523 | errorLogEntry->DumpData[i] = dumpData[i];
|
---|
1524 |
|
---|
1525 | IoWriteErrorLogEntry(errorLogEntry);
|
---|
1526 | }
|
---|
1527 | }
|
---|
1528 |
|
---|
1529 | //
|
---|
1530 | // Initialize current keyboard set packet state.
|
---|
1531 | //
|
---|
1532 |
|
---|
1533 | deviceExtension->KeyboardExtension.CurrentOutput.State = Idle;
|
---|
1534 | deviceExtension->KeyboardExtension.CurrentOutput.FirstByte = 0;
|
---|
1535 | deviceExtension->KeyboardExtension.CurrentOutput.LastByte = 0;
|
---|
1536 |
|
---|
1537 | I8xPrint((2, "I8042PRT-I8xInitializeKeyboard: exit\n"));
|
---|
1538 |
|
---|
1539 | return(status);
|
---|
1540 | }
|
---|
1541 | |
---|
1542 |
|
---|
1543 | VOID
|
---|
1544 | I8xKeyboardConfiguration(
|
---|
1545 | IN PINIT_EXTENSION InitializationData,
|
---|
1546 | IN PUNICODE_STRING RegistryPath,
|
---|
1547 | IN PUNICODE_STRING KeyboardDeviceName,
|
---|
1548 | IN PUNICODE_STRING PointerDeviceName
|
---|
1549 | )
|
---|
1550 |
|
---|
1551 | /*++
|
---|
1552 |
|
---|
1553 | Routine Description:
|
---|
1554 |
|
---|
1555 | This routine retrieves the configuration information for the keyboard.
|
---|
1556 |
|
---|
1557 | Arguments:
|
---|
1558 |
|
---|
1559 | InitializationData - Pointer to the initialization data, including the
|
---|
1560 | device extension.
|
---|
1561 |
|
---|
1562 | RegistryPath - Pointer to the null-terminated Unicode name of the
|
---|
1563 | registry path for this driver.
|
---|
1564 |
|
---|
1565 | KeyboardDeviceName - Pointer to the Unicode string that will receive
|
---|
1566 | the keyboard port device name.
|
---|
1567 |
|
---|
1568 | PointerDeviceName - Pointer to the Unicode string that will receive
|
---|
1569 | the pointer port device name.
|
---|
1570 |
|
---|
1571 | Return Value:
|
---|
1572 |
|
---|
1573 | None. As a side-effect, may set DeviceExtension->HardwarePresent.
|
---|
1574 |
|
---|
1575 | --*/
|
---|
1576 | {
|
---|
1577 | PDEVICE_EXTENSION deviceExtension = &(InitializationData->DeviceExtension);
|
---|
1578 | NTSTATUS status = STATUS_SUCCESS;
|
---|
1579 | PI8042_CONFIGURATION_INFORMATION configuration;
|
---|
1580 | INTERFACE_TYPE interfaceType;
|
---|
1581 | CONFIGURATION_TYPE controllerType = KeyboardController;
|
---|
1582 | CONFIGURATION_TYPE peripheralType = KeyboardPeripheral;
|
---|
1583 | PKEYBOARD_ID keyboardId;
|
---|
1584 | ULONG i;
|
---|
1585 |
|
---|
1586 | for (i = 0; i < MaximumInterfaceType; i++) {
|
---|
1587 |
|
---|
1588 | //
|
---|
1589 | // Get the registry information for this device.
|
---|
1590 | //
|
---|
1591 |
|
---|
1592 | interfaceType = i;
|
---|
1593 | status = IoQueryDeviceDescription(&interfaceType,
|
---|
1594 | NULL,
|
---|
1595 | &controllerType,
|
---|
1596 | NULL,
|
---|
1597 | &peripheralType,
|
---|
1598 | NULL,
|
---|
1599 | I8xKeyboardPeripheralCallout,
|
---|
1600 | (PVOID) InitializationData);
|
---|
1601 |
|
---|
1602 | if (deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT) {
|
---|
1603 |
|
---|
1604 | //
|
---|
1605 | // Get the service parameters (e.g., user-configurable number
|
---|
1606 | // of resends, polling iterations, etc.).
|
---|
1607 | //
|
---|
1608 |
|
---|
1609 | I8xServiceParameters(
|
---|
1610 | InitializationData,
|
---|
1611 | RegistryPath,
|
---|
1612 | KeyboardDeviceName,
|
---|
1613 | PointerDeviceName
|
---|
1614 | );
|
---|
1615 |
|
---|
1616 | configuration = &(InitializationData->DeviceExtension.Configuration);
|
---|
1617 |
|
---|
1618 | keyboardId = &configuration->KeyboardAttributes.KeyboardIdentifier;
|
---|
1619 | if (!ENHANCED_KEYBOARD(*keyboardId)) {
|
---|
1620 | I8xPrint((
|
---|
1621 | 1,
|
---|
1622 | "I8042PRT-I8xKeyboardConfiguration: Old AT-style keyboard\n"
|
---|
1623 | ));
|
---|
1624 | configuration->PollingIterations =
|
---|
1625 | configuration->PollingIterationsMaximum;
|
---|
1626 | }
|
---|
1627 |
|
---|
1628 | //
|
---|
1629 | // Initialize keyboard-specific configuration parameters.
|
---|
1630 | //
|
---|
1631 |
|
---|
1632 | configuration->KeyboardAttributes.NumberOfFunctionKeys =
|
---|
1633 | KeyboardTypeInformation[keyboardId->Type - 1].NumberOfFunctionKeys;
|
---|
1634 | configuration->KeyboardAttributes.NumberOfIndicators =
|
---|
1635 | KeyboardTypeInformation[keyboardId->Type - 1].NumberOfIndicators;
|
---|
1636 | configuration->KeyboardAttributes.NumberOfKeysTotal =
|
---|
1637 | KeyboardTypeInformation[keyboardId->Type - 1].NumberOfKeysTotal;
|
---|
1638 |
|
---|
1639 | configuration->KeyboardAttributes.KeyboardMode =
|
---|
1640 | KEYBOARD_SCAN_CODE_SET;
|
---|
1641 |
|
---|
1642 | configuration->KeyboardAttributes.KeyRepeatMinimum.Rate =
|
---|
1643 | KEYBOARD_TYPEMATIC_RATE_MINIMUM;
|
---|
1644 | configuration->KeyboardAttributes.KeyRepeatMinimum.Delay =
|
---|
1645 | KEYBOARD_TYPEMATIC_DELAY_MINIMUM;
|
---|
1646 | configuration->KeyboardAttributes.KeyRepeatMaximum.Rate =
|
---|
1647 | KEYBOARD_TYPEMATIC_RATE_MAXIMUM;
|
---|
1648 | configuration->KeyboardAttributes.KeyRepeatMaximum.Delay =
|
---|
1649 | KEYBOARD_TYPEMATIC_DELAY_MAXIMUM;
|
---|
1650 | configuration->KeyRepeatCurrent.Rate =
|
---|
1651 | KEYBOARD_TYPEMATIC_RATE_DEFAULT;
|
---|
1652 | configuration->KeyRepeatCurrent.Delay =
|
---|
1653 | KEYBOARD_TYPEMATIC_DELAY_DEFAULT;
|
---|
1654 |
|
---|
1655 | break;
|
---|
1656 |
|
---|
1657 | } else {
|
---|
1658 | I8xPrint((
|
---|
1659 | 1,
|
---|
1660 | "I8042PRT-I8xKeyboardConfiguration: IoQueryDeviceDescription for bus type %d failed\n",
|
---|
1661 | interfaceType
|
---|
1662 | ));
|
---|
1663 | }
|
---|
1664 | }
|
---|
1665 | }
|
---|
1666 | |
---|
1667 |
|
---|
1668 | VOID
|
---|
1669 | I8xKeyboardInitiateIo(
|
---|
1670 | IN PVOID Context
|
---|
1671 | )
|
---|
1672 |
|
---|
1673 | /*++
|
---|
1674 |
|
---|
1675 | Routine Description:
|
---|
1676 |
|
---|
1677 | This routine is called synchronously from I8xKeyboardInitiateWrapper and
|
---|
1678 | the ISR to initiate an I/O operation for the keyboard device.
|
---|
1679 |
|
---|
1680 | Arguments:
|
---|
1681 |
|
---|
1682 | Context - Pointer to the device object.
|
---|
1683 |
|
---|
1684 | Return Value:
|
---|
1685 |
|
---|
1686 | None.
|
---|
1687 |
|
---|
1688 | --*/
|
---|
1689 |
|
---|
1690 | {
|
---|
1691 | PDEVICE_EXTENSION deviceExtension;
|
---|
1692 | PDEVICE_OBJECT deviceObject;
|
---|
1693 | KEYBOARD_SET_PACKET keyboardPacket;
|
---|
1694 |
|
---|
1695 | I8xPrint((2, "I8042PRT-I8xKeyboardInitiateIo: enter\n"));
|
---|
1696 |
|
---|
1697 | //
|
---|
1698 | // Get the device extension.
|
---|
1699 | //
|
---|
1700 |
|
---|
1701 | deviceObject = (PDEVICE_OBJECT) Context;
|
---|
1702 | deviceExtension = deviceObject->DeviceExtension;
|
---|
1703 |
|
---|
1704 | //
|
---|
1705 | // Set the timeout value.
|
---|
1706 | //
|
---|
1707 |
|
---|
1708 | deviceExtension->TimerCount = I8042_ASYNC_TIMEOUT;
|
---|
1709 |
|
---|
1710 | //
|
---|
1711 | // Get the current set request packet to work on.
|
---|
1712 | //
|
---|
1713 |
|
---|
1714 | keyboardPacket = deviceExtension->KeyboardExtension.CurrentOutput;
|
---|
1715 |
|
---|
1716 | if (deviceExtension->KeyboardExtension.CurrentOutput.State
|
---|
1717 | == SendFirstByte){
|
---|
1718 |
|
---|
1719 | I8xPrint((
|
---|
1720 | 2,
|
---|
1721 | "I8042PRT-I8xKeyboardInitiateIo: send first byte 0x%x\n",
|
---|
1722 | keyboardPacket.FirstByte
|
---|
1723 | ));
|
---|
1724 |
|
---|
1725 | //
|
---|
1726 | // Send the first byte of a 2-byte command sequence to the
|
---|
1727 | // keyboard controller, asynchronously.
|
---|
1728 | //
|
---|
1729 |
|
---|
1730 | I8xPutByteAsynchronous(
|
---|
1731 | (CCHAR) DataPort,
|
---|
1732 | deviceExtension,
|
---|
1733 | keyboardPacket.FirstByte
|
---|
1734 | );
|
---|
1735 |
|
---|
1736 | } else if (deviceExtension->KeyboardExtension.CurrentOutput.State
|
---|
1737 | == SendLastByte) {
|
---|
1738 |
|
---|
1739 | I8xPrint((
|
---|
1740 | 2,
|
---|
1741 | "I8042PRT-I8xKeyboardInitiateIo: send last byte 0x%x\n",
|
---|
1742 | keyboardPacket.LastByte
|
---|
1743 | ));
|
---|
1744 |
|
---|
1745 | //
|
---|
1746 | // Send the last byte of a command sequence to the keyboard
|
---|
1747 | // controller, asynchronously.
|
---|
1748 | //
|
---|
1749 |
|
---|
1750 | I8xPutByteAsynchronous(
|
---|
1751 | (CCHAR) DataPort,
|
---|
1752 | deviceExtension,
|
---|
1753 | keyboardPacket.LastByte
|
---|
1754 | );
|
---|
1755 |
|
---|
1756 | } else {
|
---|
1757 |
|
---|
1758 | I8xPrint((2, "I8042PRT-I8xKeyboardInitiateIo: INVALID REQUEST\n"));
|
---|
1759 |
|
---|
1760 | //
|
---|
1761 | // Queue a DPC to log an internal driver error.
|
---|
1762 | //
|
---|
1763 |
|
---|
1764 | KeInsertQueueDpc(
|
---|
1765 | &deviceExtension->ErrorLogDpc,
|
---|
1766 | (PIRP) NULL,
|
---|
1767 | (PVOID) (ULONG) I8042_INVALID_INITIATE_STATE);
|
---|
1768 |
|
---|
1769 | ASSERT(FALSE);
|
---|
1770 | }
|
---|
1771 |
|
---|
1772 | I8xPrint((2, "I8042PRT-I8xKeyboardInitiateIo: exit\n"));
|
---|
1773 |
|
---|
1774 | return;
|
---|
1775 | }
|
---|
1776 | |
---|
1777 |
|
---|
1778 | VOID
|
---|
1779 | I8xKeyboardInitiateWrapper(
|
---|
1780 | IN PVOID Context
|
---|
1781 | )
|
---|
1782 |
|
---|
1783 | /*++
|
---|
1784 |
|
---|
1785 | Routine Description:
|
---|
1786 |
|
---|
1787 | This routine is called from StartIo synchronously. It sets up the
|
---|
1788 | CurrentOutput and ResendCount fields in the device extension, and
|
---|
1789 | then calls I8xKeyboardInitiateIo to do the real work.
|
---|
1790 |
|
---|
1791 | Arguments:
|
---|
1792 |
|
---|
1793 | Context - Pointer to the context structure containing the first and
|
---|
1794 | last bytes of the send sequence.
|
---|
1795 |
|
---|
1796 | Return Value:
|
---|
1797 |
|
---|
1798 | None.
|
---|
1799 |
|
---|
1800 | --*/
|
---|
1801 |
|
---|
1802 | {
|
---|
1803 | PDEVICE_OBJECT deviceObject;
|
---|
1804 | PDEVICE_EXTENSION deviceExtension;
|
---|
1805 |
|
---|
1806 | //
|
---|
1807 | // Get a pointer to the device object from the context argument.
|
---|
1808 | //
|
---|
1809 |
|
---|
1810 | deviceObject = ((PKEYBOARD_INITIATE_CONTEXT) Context)->DeviceObject;
|
---|
1811 |
|
---|
1812 | //
|
---|
1813 | // Set up CurrentOutput state for this operation.
|
---|
1814 | //
|
---|
1815 |
|
---|
1816 | deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
|
---|
1817 |
|
---|
1818 | deviceExtension->KeyboardExtension.CurrentOutput.State = SendFirstByte;
|
---|
1819 | deviceExtension->KeyboardExtension.CurrentOutput.FirstByte =
|
---|
1820 | ((PKEYBOARD_INITIATE_CONTEXT) Context)->FirstByte;
|
---|
1821 | deviceExtension->KeyboardExtension.CurrentOutput.LastByte =
|
---|
1822 | ((PKEYBOARD_INITIATE_CONTEXT) Context)->LastByte;
|
---|
1823 |
|
---|
1824 | //
|
---|
1825 | // We're starting a new operation, so reset the resend count.
|
---|
1826 | //
|
---|
1827 |
|
---|
1828 | deviceExtension->KeyboardExtension.ResendCount = 0;
|
---|
1829 |
|
---|
1830 | //
|
---|
1831 | // Initiate the keyboard I/O operation. Note that we were called
|
---|
1832 | // using KeSynchronizeExecution, so I8xKeyboardInitiateIo is also
|
---|
1833 | // synchronized with the keyboard ISR.
|
---|
1834 | //
|
---|
1835 |
|
---|
1836 | I8xKeyboardInitiateIo((PVOID) deviceObject);
|
---|
1837 |
|
---|
1838 | }
|
---|
1839 | |
---|
1840 |
|
---|
1841 | NTSTATUS
|
---|
1842 | I8xKeyboardPeripheralCallout(
|
---|
1843 | IN PVOID Context,
|
---|
1844 | IN PUNICODE_STRING PathName,
|
---|
1845 | IN INTERFACE_TYPE BusType,
|
---|
1846 | IN ULONG BusNumber,
|
---|
1847 | IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
|
---|
1848 | IN CONFIGURATION_TYPE ControllerType,
|
---|
1849 | IN ULONG ControllerNumber,
|
---|
1850 | IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
|
---|
1851 | IN CONFIGURATION_TYPE PeripheralType,
|
---|
1852 | IN ULONG PeripheralNumber,
|
---|
1853 | IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
|
---|
1854 | )
|
---|
1855 |
|
---|
1856 | /*++
|
---|
1857 |
|
---|
1858 | Routine Description:
|
---|
1859 |
|
---|
1860 | This is the callout routine sent as a parameter to
|
---|
1861 | IoQueryDeviceDescription. It grabs the keyboard controller and
|
---|
1862 | peripheral configuration information.
|
---|
1863 |
|
---|
1864 | Arguments:
|
---|
1865 |
|
---|
1866 | Context - Context parameter that was passed in by the routine
|
---|
1867 | that called IoQueryDeviceDescription.
|
---|
1868 |
|
---|
1869 | PathName - The full pathname for the registry key.
|
---|
1870 |
|
---|
1871 | BusType - Bus interface type (Isa, Eisa, Mca, etc.).
|
---|
1872 |
|
---|
1873 | BusNumber - The bus sub-key (0, 1, etc.).
|
---|
1874 |
|
---|
1875 | BusInformation - Pointer to the array of pointers to the full value
|
---|
1876 | information for the bus.
|
---|
1877 |
|
---|
1878 | ControllerType - The controller type (should be KeyboardController).
|
---|
1879 |
|
---|
1880 | ControllerNumber - The controller sub-key (0, 1, etc.).
|
---|
1881 |
|
---|
1882 | ControllerInformation - Pointer to the array of pointers to the full
|
---|
1883 | value information for the controller key.
|
---|
1884 |
|
---|
1885 | PeripheralType - The peripheral type (should be KeyboardPeripheral).
|
---|
1886 |
|
---|
1887 | PeripheralNumber - The peripheral sub-key.
|
---|
1888 |
|
---|
1889 | PeripheralInformation - Pointer to the array of pointers to the full
|
---|
1890 | value information for the peripheral key.
|
---|
1891 |
|
---|
1892 |
|
---|
1893 | Return Value:
|
---|
1894 |
|
---|
1895 | None. If successful, will have the following side-effects:
|
---|
1896 |
|
---|
1897 | - Sets DeviceObject->DeviceExtension->HardwarePresent.
|
---|
1898 | - Sets configuration fields in
|
---|
1899 | DeviceObject->DeviceExtension->Configuration.
|
---|
1900 |
|
---|
1901 | --*/
|
---|
1902 | {
|
---|
1903 | PDEVICE_EXTENSION deviceExtension;
|
---|
1904 | PINIT_EXTENSION initializationData;
|
---|
1905 | PI8042_CONFIGURATION_INFORMATION configuration;
|
---|
1906 | UNICODE_STRING unicodeIdentifier;
|
---|
1907 | PUCHAR controllerData;
|
---|
1908 | PUCHAR peripheralData;
|
---|
1909 | NTSTATUS status = STATUS_SUCCESS;
|
---|
1910 | ULONG i;
|
---|
1911 | ULONG listCount;
|
---|
1912 | PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor;
|
---|
1913 | CM_PARTIAL_RESOURCE_DESCRIPTOR tmpResourceDescriptor;
|
---|
1914 | PCM_KEYBOARD_DEVICE_DATA keyboardSpecificData;
|
---|
1915 | BOOLEAN defaultInterruptShare;
|
---|
1916 | KINTERRUPT_MODE defaultInterruptMode;
|
---|
1917 |
|
---|
1918 | I8xPrint((
|
---|
1919 | 1,
|
---|
1920 | "I8042PRT-I8xKeyboardPeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n",
|
---|
1921 | PathName, BusType, BusNumber
|
---|
1922 | ));
|
---|
1923 | I8xPrint((
|
---|
1924 | 1,
|
---|
1925 | " Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n",
|
---|
1926 | ControllerType, ControllerNumber, ControllerInformation
|
---|
1927 | ));
|
---|
1928 | I8xPrint((
|
---|
1929 | 1,
|
---|
1930 | " Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n",
|
---|
1931 | PeripheralType, PeripheralNumber, PeripheralInformation
|
---|
1932 | ));
|
---|
1933 |
|
---|
1934 |
|
---|
1935 | //
|
---|
1936 | // Get the length of the peripheral identifier information.
|
---|
1937 | //
|
---|
1938 |
|
---|
1939 | unicodeIdentifier.Length = (USHORT)
|
---|
1940 | (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength;
|
---|
1941 |
|
---|
1942 | //
|
---|
1943 | // If we already have the configuration information for the
|
---|
1944 | // keyboard peripheral, or if the peripheral identifier is missing,
|
---|
1945 | // just return.
|
---|
1946 | //
|
---|
1947 |
|
---|
1948 | initializationData = (PINIT_EXTENSION) Context;
|
---|
1949 | deviceExtension = &(initializationData->DeviceExtension);
|
---|
1950 |
|
---|
1951 | if ((deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)
|
---|
1952 | || (unicodeIdentifier.Length == 0)) {
|
---|
1953 | return (status);
|
---|
1954 | }
|
---|
1955 |
|
---|
1956 | configuration = &deviceExtension->Configuration;
|
---|
1957 |
|
---|
1958 | //
|
---|
1959 | // Get the identifier information for the peripheral.
|
---|
1960 | //
|
---|
1961 |
|
---|
1962 | unicodeIdentifier.MaximumLength = unicodeIdentifier.Length;
|
---|
1963 | unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation +
|
---|
1964 | IoQueryDeviceIdentifier))) +
|
---|
1965 | (*(PeripheralInformation +
|
---|
1966 | IoQueryDeviceIdentifier))->DataOffset);
|
---|
1967 | I8xPrint((
|
---|
1968 | 1,
|
---|
1969 | "I8042PRT-I8xKeyboardPeripheralCallout: Keyboard type %ws\n",
|
---|
1970 | unicodeIdentifier.Buffer
|
---|
1971 | ));
|
---|
1972 |
|
---|
1973 | deviceExtension->HardwarePresent |= KEYBOARD_HARDWARE_PRESENT;
|
---|
1974 |
|
---|
1975 | //
|
---|
1976 | // Initialize the Keyboard Type to unknown.
|
---|
1977 | //
|
---|
1978 |
|
---|
1979 | configuration->KeyboardAttributes.KeyboardIdentifier.Type = 0;
|
---|
1980 | configuration->KeyboardAttributes.KeyboardIdentifier.Subtype = 0;
|
---|
1981 |
|
---|
1982 | //
|
---|
1983 | // Look through the peripheral's resource list for device-specific
|
---|
1984 | // information. The keyboard-specific information is defined
|
---|
1985 | // in sdk\inc\ntconfig.h.
|
---|
1986 | //
|
---|
1987 |
|
---|
1988 | if ((*(PeripheralInformation + IoQueryDeviceConfigurationData))->DataLength != 0){
|
---|
1989 | peripheralData = ((PUCHAR) (*(PeripheralInformation +
|
---|
1990 | IoQueryDeviceConfigurationData))) +
|
---|
1991 | (*(PeripheralInformation +
|
---|
1992 | IoQueryDeviceConfigurationData))->DataOffset;
|
---|
1993 |
|
---|
1994 | peripheralData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
|
---|
1995 | PartialResourceList);
|
---|
1996 |
|
---|
1997 | listCount = ((PCM_PARTIAL_RESOURCE_LIST) peripheralData)->Count;
|
---|
1998 |
|
---|
1999 | resourceDescriptor =
|
---|
2000 | ((PCM_PARTIAL_RESOURCE_LIST) peripheralData)->PartialDescriptors;
|
---|
2001 |
|
---|
2002 | for (i = 0; i < listCount; i++, resourceDescriptor++) {
|
---|
2003 | switch(resourceDescriptor->Type) {
|
---|
2004 |
|
---|
2005 | case CmResourceTypeDeviceSpecific:
|
---|
2006 |
|
---|
2007 | //
|
---|
2008 | // Get the keyboard type, subtype, and the initial
|
---|
2009 | // settings for the LEDs.
|
---|
2010 | //
|
---|
2011 |
|
---|
2012 | keyboardSpecificData =
|
---|
2013 | (PCM_KEYBOARD_DEVICE_DATA)(((PUCHAR)resourceDescriptor)
|
---|
2014 | + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
---|
2015 | if (keyboardSpecificData->Type<= NUM_KNOWN_KEYBOARD_TYPES){
|
---|
2016 | configuration->KeyboardAttributes.KeyboardIdentifier.Type =
|
---|
2017 | keyboardSpecificData->Type;
|
---|
2018 | }
|
---|
2019 | configuration->KeyboardAttributes.KeyboardIdentifier.Subtype =
|
---|
2020 | keyboardSpecificData->Subtype;
|
---|
2021 | configuration->KeyboardIndicators.LedFlags =
|
---|
2022 | (keyboardSpecificData->KeyboardFlags >> 4) & 7;
|
---|
2023 |
|
---|
2024 | break;
|
---|
2025 |
|
---|
2026 | default:
|
---|
2027 | break;
|
---|
2028 | }
|
---|
2029 | }
|
---|
2030 | }
|
---|
2031 |
|
---|
2032 | //
|
---|
2033 | // If no keyboard-specific information (i.e., keyboard type, subtype,
|
---|
2034 | // and initial LED settings) was found, use the keyboard driver
|
---|
2035 | // defaults.
|
---|
2036 | //
|
---|
2037 |
|
---|
2038 | if (configuration->KeyboardAttributes.KeyboardIdentifier.Type == 0) {
|
---|
2039 |
|
---|
2040 | #if defined(JAPAN) && defined(_X86_)
|
---|
2041 | //Fujitsu Aug.23.1994
|
---|
2042 | // if not connect keyboard hardware,Insert 106 keyboard type to each structure members
|
---|
2043 | // for realizing "keyboard-less system".
|
---|
2044 |
|
---|
2045 | configuration->KeyboardAttributes.KeyboardIdentifier.Type = 0x4;
|
---|
2046 | configuration->KeyboardAttributes.KeyboardIdentifier.Subtype = 0;
|
---|
2047 | configuration->KeyboardIndicators.LedFlags = KEYBOARD_INDICATORS_DEFAULT;
|
---|
2048 | #endif
|
---|
2049 |
|
---|
2050 | I8xPrint((
|
---|
2051 | 1,
|
---|
2052 | "I8042PRT-I8xKeyboardPeripheralCallout: Using default keyboard type\n"
|
---|
2053 | ));
|
---|
2054 |
|
---|
2055 | configuration->KeyboardAttributes.KeyboardIdentifier.Type =
|
---|
2056 | KEYBOARD_TYPE_DEFAULT;
|
---|
2057 | configuration->KeyboardIndicators.LedFlags =
|
---|
2058 | KEYBOARD_INDICATORS_DEFAULT;
|
---|
2059 |
|
---|
2060 | }
|
---|
2061 |
|
---|
2062 | I8xPrint((
|
---|
2063 | 1,
|
---|
2064 | "I8042PRT-I8xKeyboardPeripheralCallout: Keyboard device specific data --\n"
|
---|
2065 | ));
|
---|
2066 | I8xPrint((
|
---|
2067 | 1,
|
---|
2068 | " Type = %d, Subtype = %d, Initial LEDs = 0x%x\n",
|
---|
2069 | configuration->KeyboardAttributes.KeyboardIdentifier.Type,
|
---|
2070 | configuration->KeyboardAttributes.KeyboardIdentifier.Subtype,
|
---|
2071 | configuration->KeyboardIndicators.LedFlags
|
---|
2072 | ));
|
---|
2073 |
|
---|
2074 | //
|
---|
2075 | // Get the bus information.
|
---|
2076 | //
|
---|
2077 |
|
---|
2078 | configuration->InterfaceType = BusType;
|
---|
2079 | configuration->BusNumber = BusNumber;
|
---|
2080 | configuration->FloatingSave = I8042_FLOATING_SAVE;
|
---|
2081 |
|
---|
2082 | if (BusType == MicroChannel) {
|
---|
2083 | defaultInterruptShare = TRUE;
|
---|
2084 | defaultInterruptMode = LevelSensitive;
|
---|
2085 | } else {
|
---|
2086 | defaultInterruptShare = I8042_INTERRUPT_SHARE;
|
---|
2087 | defaultInterruptMode = I8042_INTERRUPT_MODE;
|
---|
2088 | }
|
---|
2089 |
|
---|
2090 | //
|
---|
2091 | // Look through the controller's resource list for interrupt and port
|
---|
2092 | // configuration information.
|
---|
2093 | //
|
---|
2094 |
|
---|
2095 | if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){
|
---|
2096 | controllerData = ((PUCHAR) (*(ControllerInformation +
|
---|
2097 | IoQueryDeviceConfigurationData))) +
|
---|
2098 | (*(ControllerInformation +
|
---|
2099 | IoQueryDeviceConfigurationData))->DataOffset;
|
---|
2100 |
|
---|
2101 | controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
|
---|
2102 | PartialResourceList);
|
---|
2103 |
|
---|
2104 | listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count;
|
---|
2105 |
|
---|
2106 | resourceDescriptor =
|
---|
2107 | ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors;
|
---|
2108 |
|
---|
2109 | for (i = 0; i < listCount; i++, resourceDescriptor++) {
|
---|
2110 | switch(resourceDescriptor->Type) {
|
---|
2111 | case CmResourceTypePort:
|
---|
2112 |
|
---|
2113 | //
|
---|
2114 | // Copy the port information. We will sort the port list
|
---|
2115 | // into ascending order based on the starting port address
|
---|
2116 | // later (note that we *know* there are a max of two port
|
---|
2117 | // ranges for the i8042).
|
---|
2118 | //
|
---|
2119 |
|
---|
2120 | ASSERT(configuration->PortListCount < MaximumPortCount);
|
---|
2121 | configuration->PortList[configuration->PortListCount] =
|
---|
2122 | *resourceDescriptor;
|
---|
2123 | configuration->PortList[configuration->PortListCount].ShareDisposition =
|
---|
2124 | I8042_REGISTER_SHARE? CmResourceShareShared:
|
---|
2125 | CmResourceShareDriverExclusive;
|
---|
2126 | configuration->PortListCount += 1;
|
---|
2127 |
|
---|
2128 | break;
|
---|
2129 |
|
---|
2130 | case CmResourceTypeInterrupt:
|
---|
2131 |
|
---|
2132 | //
|
---|
2133 | // Copy the interrupt information.
|
---|
2134 | //
|
---|
2135 |
|
---|
2136 | configuration->KeyboardInterrupt = *resourceDescriptor;
|
---|
2137 | configuration->KeyboardInterrupt.ShareDisposition =
|
---|
2138 | defaultInterruptShare? CmResourceShareShared :
|
---|
2139 | CmResourceShareDeviceExclusive;
|
---|
2140 |
|
---|
2141 | break;
|
---|
2142 |
|
---|
2143 | case CmResourceTypeDeviceSpecific:
|
---|
2144 | break;
|
---|
2145 |
|
---|
2146 | default:
|
---|
2147 | break;
|
---|
2148 | }
|
---|
2149 | }
|
---|
2150 | }
|
---|
2151 |
|
---|
2152 | //
|
---|
2153 | // If no interrupt configuration information was found, use the
|
---|
2154 | // keyboard driver defaults.
|
---|
2155 | //
|
---|
2156 |
|
---|
2157 | if (!(configuration->KeyboardInterrupt.Type & CmResourceTypeInterrupt)) {
|
---|
2158 |
|
---|
2159 | I8xPrint((
|
---|
2160 | 1,
|
---|
2161 | "I8042PRT-I8xKeyboardPeripheralCallout: Using default keyboard interrupt config\n"
|
---|
2162 | ));
|
---|
2163 |
|
---|
2164 | configuration->KeyboardInterrupt.Type = CmResourceTypeInterrupt;
|
---|
2165 | configuration->KeyboardInterrupt.ShareDisposition =
|
---|
2166 | defaultInterruptShare? CmResourceShareShared :
|
---|
2167 | CmResourceShareDeviceExclusive;
|
---|
2168 | configuration->KeyboardInterrupt.Flags =
|
---|
2169 | (defaultInterruptMode == Latched)? CM_RESOURCE_INTERRUPT_LATCHED :
|
---|
2170 | CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
---|
2171 | configuration->KeyboardInterrupt.u.Interrupt.Level = KEYBOARD_IRQL;
|
---|
2172 | configuration->KeyboardInterrupt.u.Interrupt.Vector = KEYBOARD_VECTOR;
|
---|
2173 | }
|
---|
2174 |
|
---|
2175 | I8xPrint((
|
---|
2176 | 1,
|
---|
2177 | "I8042PRT-I8xKeyboardPeripheralCallout: Keyboard interrupt config --\n"
|
---|
2178 | ));
|
---|
2179 | I8xPrint((
|
---|
2180 | 1,
|
---|
2181 | " %s, %s, Irq = %d\n",
|
---|
2182 | configuration->KeyboardInterrupt.ShareDisposition == CmResourceShareShared?
|
---|
2183 | "Sharable" : "NonSharable",
|
---|
2184 | configuration->KeyboardInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED?
|
---|
2185 | "Latched" : "Level Sensitive",
|
---|
2186 | configuration->KeyboardInterrupt.u.Interrupt.Vector
|
---|
2187 | ));
|
---|
2188 |
|
---|
2189 | //
|
---|
2190 | // If no port configuration information was found, use the
|
---|
2191 | // keyboard driver defaults.
|
---|
2192 | //
|
---|
2193 |
|
---|
2194 | if (configuration->PortListCount == 0) {
|
---|
2195 |
|
---|
2196 | //
|
---|
2197 | // No port configuration information was found, so use
|
---|
2198 | // the driver defaults.
|
---|
2199 | //
|
---|
2200 |
|
---|
2201 | I8xPrint((
|
---|
2202 | 1,
|
---|
2203 | "I8042PRT-I8xKeyboardPeripheralCallout: Using default port config\n"
|
---|
2204 | ));
|
---|
2205 |
|
---|
2206 | configuration->PortList[DataPort].Type = CmResourceTypePort;
|
---|
2207 | configuration->PortList[DataPort].Flags = I8042_PORT_TYPE;
|
---|
2208 | configuration->PortList[DataPort].ShareDisposition =
|
---|
2209 | I8042_REGISTER_SHARE? CmResourceShareShared:
|
---|
2210 | CmResourceShareDriverExclusive;
|
---|
2211 | configuration->PortList[DataPort].u.Port.Start.LowPart =
|
---|
2212 | I8042_PHYSICAL_BASE + I8042_DATA_REGISTER_OFFSET;
|
---|
2213 | configuration->PortList[DataPort].u.Port.Start.HighPart = 0;
|
---|
2214 | configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH;
|
---|
2215 |
|
---|
2216 | configuration->PortList[CommandPort].Type = CmResourceTypePort;
|
---|
2217 | configuration->PortList[CommandPort].Flags = I8042_PORT_TYPE;
|
---|
2218 | configuration->PortList[CommandPort].ShareDisposition =
|
---|
2219 | I8042_REGISTER_SHARE? CmResourceShareShared:
|
---|
2220 | CmResourceShareDriverExclusive;
|
---|
2221 | configuration->PortList[CommandPort].u.Port.Start.LowPart =
|
---|
2222 | I8042_PHYSICAL_BASE + I8042_COMMAND_REGISTER_OFFSET;
|
---|
2223 | configuration->PortList[CommandPort].u.Port.Start.HighPart = 0;
|
---|
2224 | configuration->PortList[CommandPort].u.Port.Length = I8042_REGISTER_LENGTH;
|
---|
2225 |
|
---|
2226 | configuration->PortListCount = 2;
|
---|
2227 | } else if (configuration->PortListCount == 1) {
|
---|
2228 |
|
---|
2229 | //
|
---|
2230 | // Kludge for Jazz machines. Their ARC firmware neglects to
|
---|
2231 | // separate out the port addresses, so fix that up here.
|
---|
2232 | //
|
---|
2233 |
|
---|
2234 | configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH;
|
---|
2235 | configuration->PortList[CommandPort] = configuration->PortList[DataPort];
|
---|
2236 | configuration->PortList[CommandPort].u.Port.Start.LowPart +=
|
---|
2237 | I8042_COMMAND_REGISTER_OFFSET;
|
---|
2238 | configuration->PortListCount += 1;
|
---|
2239 | } else {
|
---|
2240 |
|
---|
2241 | //
|
---|
2242 | // Put the lowest port address range in the DataPort element of
|
---|
2243 | // the port list.
|
---|
2244 | //
|
---|
2245 |
|
---|
2246 | if (configuration->PortList[CommandPort].u.Port.Start.LowPart
|
---|
2247 | < configuration->PortList[DataPort].u.Port.Start.LowPart) {
|
---|
2248 | tmpResourceDescriptor = configuration->PortList[DataPort];
|
---|
2249 | configuration->PortList[DataPort] =
|
---|
2250 | configuration->PortList[CommandPort];
|
---|
2251 | configuration->PortList[CommandPort] = tmpResourceDescriptor;
|
---|
2252 | }
|
---|
2253 | }
|
---|
2254 |
|
---|
2255 | #ifdef PNP_IDENTIFY
|
---|
2256 | //
|
---|
2257 | // We're going to use the keyboard based on this data,
|
---|
2258 | // so make sure we can tell PNP that we've claimed it later on
|
---|
2259 | //
|
---|
2260 |
|
---|
2261 | initializationData->KeyboardConfig.InterfaceType = BusType;
|
---|
2262 | initializationData->KeyboardConfig.InterfaceNumber = BusNumber;
|
---|
2263 | initializationData->KeyboardConfig.ControllerType = ControllerType;
|
---|
2264 | initializationData->KeyboardConfig.ControllerNumber = ControllerNumber;
|
---|
2265 | initializationData->KeyboardConfig.PeripheralType = PeripheralType;
|
---|
2266 | initializationData->KeyboardConfig.PeripheralNumber = PeripheralNumber;
|
---|
2267 | #endif
|
---|
2268 |
|
---|
2269 | for (i = 0; i < configuration->PortListCount; i++) {
|
---|
2270 |
|
---|
2271 | I8xPrint((
|
---|
2272 | 1,
|
---|
2273 | " %s, Ports 0x%x - 0x%x\n",
|
---|
2274 | configuration->PortList[i].ShareDisposition
|
---|
2275 | == CmResourceShareShared? "Sharable" : "NonSharable",
|
---|
2276 | configuration->PortList[i].u.Port.Start.LowPart,
|
---|
2277 | configuration->PortList[i].u.Port.Start.LowPart +
|
---|
2278 | configuration->PortList[i].u.Port.Length - 1
|
---|
2279 | ));
|
---|
2280 | }
|
---|
2281 |
|
---|
2282 | return(status);
|
---|
2283 | }
|
---|