Annotation of ntddk/src/input/i8042prt/kbddep.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.