Annotation of ntddk/src/input/i8042prt/moudep.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:     moudep.c
                      9: 
                     10: Abstract:
                     11: 
                     12:     The initialization and hardware-dependent portions of
                     13:     the Intel i8042 port driver which are specific to
                     14:     the auxiliary (PS/2 mouse) device.  
                     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,I8xMouseConfiguration)
                     46: #pragma alloc_text(init,I8xMousePeripheralCallout)
                     47: #pragma alloc_text(init,I8xInitializeMouse)
                     48: #endif
                     49: 
                     50: 
                     51: BOOLEAN
                     52: I8042MouseInterruptService(
                     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 mouse device.
                     62: 
                     63: Arguments:
                     64: 
                     65:     Interrupt - A pointer to the interrupt object for this interrupt.
                     66: 
                     67:     Context - A pointer to the device object.
                     68: 
                     69: Return Value:
                     70: 
                     71:     Returns TRUE if the interrupt was expected (and therefore processed);
                     72:     otherwise, FALSE is returned.
                     73: 
                     74: --*/
                     75: 
                     76: {
                     77:     PDEVICE_EXTENSION deviceExtension;
                     78:     PDEVICE_OBJECT deviceObject;
                     79:     LARGE_INTEGER tickDelta, newTick;
                     80:     UCHAR previousButtons;
                     81:     UCHAR previousSignAndOverflow;
                     82:     UCHAR byte;
                     83: 
                     84:     UNREFERENCED_PARAMETER(Interrupt);
                     85: 
                     86:     I8xPrint((2, "I8042PRT-I8042MouseInterruptService: enter\n"));
                     87: 
                     88:     deviceObject = (PDEVICE_OBJECT) Context;
                     89:     deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
                     90: 
                     91:     //
                     92:     // Verify that this device really interrupted.  Check the status
                     93:     // register.  The Output Buffer Full bit should be set, and the
                     94:     // Auxiliary Device Output Buffer Full bit should be set.
                     95:     //
                     96: 
                     97:     if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort]) 
                     98:             & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
                     99:             != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) {
                    100: 
                    101:         //
                    102:         // Stall and then try again.  The Olivetti MIPS machine
                    103:         // sometimes gets a mouse interrupt before the status
                    104:         // register is set.
                    105:         //
                    106: 
                    107:         KeStallExecutionProcessor(10);
                    108:         if ((I8X_GET_STATUS_BYTE(deviceExtension->DeviceRegisters[CommandPort]) 
                    109:                 & (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL))
                    110:                 != (OUTPUT_BUFFER_FULL|MOUSE_OUTPUT_BUFFER_FULL)) {
                    111: 
                    112:             //
                    113:             // Not our interrupt.
                    114:             //
                    115: 
                    116:             I8xPrint((
                    117:                 1, 
                    118:                 "I8042PRT-I8042MouseInterruptService: not our interrupt!\n"
                    119:                 ));
                    120:             return(FALSE);
                    121:         }
                    122:     }
                    123: 
                    124:     //
                    125:     // Read the byte from the i8042 data port.
                    126:     //
                    127: 
                    128:     I8xGetByteAsynchronous(
                    129:         (CCHAR) MouseDeviceType,
                    130:         deviceExtension,
                    131:         &byte
                    132:         );
                    133: 
                    134:     I8xPrint((
                    135:         3,
                    136:         "I8042PRT-I8042MouseInterruptService: byte 0x%x\n",
                    137:         byte
                    138:         ));
                    139: 
                    140:     //
                    141:     // Take the appropriate action, depending on the current state.
                    142:     // When the state is Idle, we expect to receive mouse button
                    143:     // data.  When the state is XMovement, we expect to receive mouse
                    144:     // motion in the X direction data.  When the state is YMovement,
                    145:     // we expect to receive mouse motion in the Y direction data.  Once
                    146:     // the Y motion data has been received, the data is queued to the
                    147:     // mouse InputData queue, the mouse ISR DPC is requested, and the
                    148:     // state returns to Idle.
                    149:     //
                    150: 
                    151:     KeQueryTickCount(&newTick);
                    152:     tickDelta = RtlLargeIntegerSubtract(
                    153:                     newTick,
                    154:                     deviceExtension->MouseExtension.PreviousTick
                    155:                     );
                    156: 
                    157:     if ((deviceExtension->MouseExtension.InputState != MouseIdle)
                    158:            && (deviceExtension->MouseExtension.InputState != MouseExpectingACK)
                    159:            && ((tickDelta.LowPart >= deviceExtension->MouseExtension.SynchTickCount)
                    160:            || (tickDelta.HighPart != 0))) {
                    161:  
                    162:         //
                    163:         // It has been a long time since we got a byte of
                    164:         // the data packet.  Assume that we are now receiving
                    165:         // the first byte of a new packet, and discard any
                    166:         // partially received packet.
                    167:         //
                    168:         // N.B.  We assume that SynchTickCount is ULONG, and avoid
                    169:         //       a LARGE_INTEGER compare with tickDelta...
                    170:         //
                    171: 
                    172:         I8xPrint((
                    173:             1,
                    174:             "I8042PRT-I8042MouseInterruptService: State was %d, synching\n",
                    175:             deviceExtension->MouseExtension.InputState
                    176:             ));
                    177: 
                    178:         deviceExtension->MouseExtension.InputState = MouseIdle;
                    179:     }
                    180: 
                    181:     deviceExtension->MouseExtension.PreviousTick = newTick;
                    182: 
                    183:     switch(deviceExtension->MouseExtension.InputState) {
                    184: 
                    185:         //
                    186:         // The mouse interrupted with a status byte.  The status byte
                    187:         // contains information on the mouse button state along with
                    188:         // the sign and overflow bits for the (yet-to-be-received)
                    189:         // X and Y motion bytes.
                    190:         //
                    191: 
                    192:         case MouseIdle:
                    193: 
                    194:             I8xPrint((
                    195:                 3,
                    196:                 "I8042PRT-I8042MouseInterruptService: mouse status byte\n"
                    197:                 ));
                    198: 
                    199:             //
                    200:             // Update CurrentInput with button transition data.
                    201:             // I.e., set a button up/down bit in the Buttons field if
                    202:             // the state of a given button has changed since we
                    203:             // received the last packet.
                    204:             //
                    205: 
                    206:             previousButtons = 
                    207:                 deviceExtension->MouseExtension.PreviousButtons;
                    208: 
                    209:             deviceExtension->MouseExtension.CurrentInput.Buttons = 0;
                    210: 
                    211:             if ((!(previousButtons & LEFT_BUTTON_DOWN)) 
                    212:                    &&  (byte & LEFT_BUTTON_DOWN)) {
                    213:                 deviceExtension->MouseExtension.CurrentInput.Buttons |=
                    214:                     MOUSE_LEFT_BUTTON_DOWN;
                    215:             } else
                    216:             if ((previousButtons & LEFT_BUTTON_DOWN) 
                    217:                    &&  !(byte & LEFT_BUTTON_DOWN)) {
                    218:                 deviceExtension->MouseExtension.CurrentInput.Buttons |=
                    219:                     MOUSE_LEFT_BUTTON_UP;
                    220:             }
                    221:             if ((!(previousButtons & RIGHT_BUTTON_DOWN)) 
                    222:                    &&  (byte & RIGHT_BUTTON_DOWN)) {
                    223:                 deviceExtension->MouseExtension.CurrentInput.Buttons |=
                    224:                     MOUSE_RIGHT_BUTTON_DOWN;
                    225:             } else
                    226:             if ((previousButtons & RIGHT_BUTTON_DOWN) 
                    227:                    &&  !(byte & RIGHT_BUTTON_DOWN)) {
                    228:                 deviceExtension->MouseExtension.CurrentInput.Buttons |=
                    229:                     MOUSE_RIGHT_BUTTON_UP;
                    230:             }
                    231:             if ((!(previousButtons & MIDDLE_BUTTON_DOWN)) 
                    232:                    &&  (byte & MIDDLE_BUTTON_DOWN)) {
                    233:                 deviceExtension->MouseExtension.CurrentInput.Buttons |=
                    234:                     MOUSE_MIDDLE_BUTTON_DOWN;
                    235:             } else
                    236:             if ((previousButtons & MIDDLE_BUTTON_DOWN) 
                    237:                    &&  !(byte & MIDDLE_BUTTON_DOWN)) {
                    238:                 deviceExtension->MouseExtension.CurrentInput.Buttons |=
                    239:                     MOUSE_MIDDLE_BUTTON_UP;
                    240:             }
                    241:             
                    242:             //
                    243:             // Save the button state for comparison the next time around.
                    244:             //
                    245: 
                    246:             deviceExtension->MouseExtension.PreviousButtons = 
                    247:                 byte & (RIGHT_BUTTON_DOWN|MIDDLE_BUTTON_DOWN|LEFT_BUTTON_DOWN);
                    248:             
                    249:             //
                    250:             // Save the sign and overflow information from the current byte.
                    251:             //
                    252: 
                    253:             deviceExtension->MouseExtension.CurrentSignAndOverflow =
                    254:                 (UCHAR) (byte & MOUSE_SIGN_OVERFLOW_MASK);
                    255: 
                    256:             //
                    257:             // Update to the next state.
                    258:             //
                    259: 
                    260:             deviceExtension->MouseExtension.InputState = XMovement;
                    261: 
                    262:             break;
                    263: 
                    264:         //
                    265:         // The mouse interrupted with the X motion byte.  Apply
                    266:         // the sign and overflow bits from the mouse status byte received
                    267:         // previously.  Attempt to correct for bogus changes in sign
                    268:         // that occur with large, rapid mouse movements.
                    269:         //
                    270: 
                    271:         case XMovement:
                    272: 
                    273:             I8xPrint((
                    274:                 3,
                    275:                 "I8042PRT-I8042MouseInterruptService: mouse LastX byte\n"
                    276:                 ));
                    277: 
                    278:             //
                    279:             // Update CurrentInput with the X motion data.
                    280:             //
                    281: 
                    282:             if (deviceExtension->MouseExtension.CurrentSignAndOverflow
                    283:                 & X_OVERFLOW) {
                    284: 
                    285:                 //
                    286:                 // Handle overflow in the X direction.  If the previous
                    287:                 // mouse movement overflowed too, ensure that the current
                    288:                 // overflow is in the same direction (i.e., that the sign
                    289:                 // is the same as it was for the previous event).  We do this
                    290:                 // to correct for hardware problems -- it should not be possible
                    291:                 // to overflow in one direction and then immediately overflow
                    292:                 // in the opposite direction.
                    293:                 //
                    294: 
                    295:                 previousSignAndOverflow =
                    296:                     deviceExtension->MouseExtension.PreviousSignAndOverflow;
                    297:                 if (previousSignAndOverflow & X_OVERFLOW) {
                    298:                     if ((previousSignAndOverflow & X_DATA_SIGN) !=
                    299:                         (deviceExtension->MouseExtension.CurrentSignAndOverflow
                    300:                          & X_DATA_SIGN)) {
                    301:                         deviceExtension->MouseExtension.CurrentSignAndOverflow
                    302:                             ^= X_DATA_SIGN;
                    303:                     }
                    304:                 }
                    305: 
                    306:                 if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
                    307:                     X_DATA_SIGN)
                    308:                     deviceExtension->MouseExtension.CurrentInput.LastX =
                    309:                         (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA;
                    310:                 else
                    311:                     deviceExtension->MouseExtension.CurrentInput.LastX =
                    312:                         (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA;
                    313: 
                    314:             } else {
                    315: 
                    316:                 //
                    317:                 // No overflow.  Just store the data, correcting for the
                    318:                 // sign if necessary.
                    319:                 //
                    320: 
                    321:                 deviceExtension->MouseExtension.CurrentInput.LastX =
                    322:                     (ULONG) byte;
                    323:                 if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
                    324:                     X_DATA_SIGN)
                    325:                     deviceExtension->MouseExtension.CurrentInput.LastX |=
                    326:                         MOUSE_MAXIMUM_NEGATIVE_DELTA;
                    327:             }
                    328: 
                    329:             //
                    330:             // Update to the next state.
                    331:             //
                    332: 
                    333:             deviceExtension->MouseExtension.InputState = YMovement;
                    334: 
                    335:             break;
                    336: 
                    337:         //
                    338:         // The mouse interrupted with the Y motion byte.  Apply
                    339:         // the sign and overflow bits from the mouse status byte received
                    340:         // previously.  [Attempt to correct for bogus changes in sign
                    341:         // that occur with large, rapid mouse movements.]  Write the
                    342:         // data to the mouse InputData queue, and queue the mouse ISR DPC
                    343:         // to complete the interrupt processing.
                    344:         //
                    345: 
                    346:         case YMovement:
                    347: 
                    348:             I8xPrint((
                    349:                 3,
                    350:                 "I8042PRT-I8042MouseInterruptService: mouse LastY byte\n"
                    351:                 ));
                    352: 
                    353:             //
                    354:             // Update CurrentInput with the Y motion data.
                    355:             //
                    356: 
                    357:             if (deviceExtension->MouseExtension.CurrentSignAndOverflow
                    358:                 & Y_OVERFLOW) {
                    359: 
                    360:                 //
                    361:                 // Handle overflow in the Y direction.  If the previous
                    362:                 // mouse movement overflowed too, ensure that the current
                    363:                 // overflow is in the same direction (i.e., that the sign
                    364:                 // is the same as it was for the previous event).  We do this
                    365:                 // to correct for hardware problems -- it should not be possible
                    366:                 // to overflow in one direction and then immediately overflow
                    367:                 // in the opposite direction.
                    368:                 //
                    369: 
                    370:                 previousSignAndOverflow =
                    371:                     deviceExtension->MouseExtension.PreviousSignAndOverflow;
                    372:                 if (previousSignAndOverflow & Y_OVERFLOW) {
                    373:                     if ((previousSignAndOverflow & Y_DATA_SIGN) !=
                    374:                         (deviceExtension->MouseExtension.CurrentSignAndOverflow
                    375:                          & Y_DATA_SIGN)) {
                    376:                         deviceExtension->MouseExtension.CurrentSignAndOverflow
                    377:                             ^= Y_DATA_SIGN;
                    378:                     }
                    379:                 }
                    380: 
                    381:                 if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
                    382:                     Y_DATA_SIGN)
                    383:                     deviceExtension->MouseExtension.CurrentInput.LastY =
                    384:                         (LONG) MOUSE_MAXIMUM_POSITIVE_DELTA;
                    385:                 else
                    386:                     deviceExtension->MouseExtension.CurrentInput.LastY =
                    387:                         (LONG) MOUSE_MAXIMUM_NEGATIVE_DELTA;
                    388: 
                    389:             } else {
                    390: 
                    391:                 //
                    392:                 // No overflow.  Just store the data, correcting for the
                    393:                 // sign if necessary.  
                    394:                 //
                    395: 
                    396:                 deviceExtension->MouseExtension.CurrentInput.LastY =
                    397:                     (ULONG) byte;
                    398:                 if (deviceExtension->MouseExtension.CurrentSignAndOverflow &
                    399:                     Y_DATA_SIGN)
                    400:                     deviceExtension->MouseExtension.CurrentInput.LastY |=
                    401:                         MOUSE_MAXIMUM_NEGATIVE_DELTA;
                    402: 
                    403:                  //
                    404:                  // Negate the LastY value (the hardware reports positive
                    405:                  // motion in the direction that we consider negative).
                    406:                  //
                    407: 
                    408:                  deviceExtension->MouseExtension.CurrentInput.LastY =
                    409:                      -deviceExtension->MouseExtension.CurrentInput.LastY;
                    410: 
                    411:             }
                    412: 
                    413:             //
                    414:             // Update our notion of the previous sign and overflow bits for
                    415:             // the start of the next mouse input sequence.
                    416:             //
                    417: 
                    418:             deviceExtension->MouseExtension.PreviousSignAndOverflow =
                    419:                 deviceExtension->MouseExtension.CurrentSignAndOverflow;
                    420: 
                    421:             //
                    422:             // If the mouse is enabled, add the data to the InputData queue
                    423:             // and queue the ISR DPC.  One might wonder why we bother to
                    424:             // do all this processing of the mouse packet, only to toss it
                    425:             // away (i.e., not queue it) at this point.  The answer is that
                    426:             // this mouse provides no data to allow the driver to determine
                    427:             // when the first byte of a packet is received -- if the driver
                    428:             // doesn't process all interrupts from the start, there is no
                    429:             // way to keep MouseExtension.InputState in synch with hardware
                    430:             // reality.
                    431:             //
                    432: 
                    433:             if (deviceExtension->MouseEnableCount) {
                    434:                 deviceExtension->MouseExtension.CurrentInput.UnitId = 
                    435:                     deviceExtension->MouseExtension.UnitId;
                    436:                 if (!I8xWriteDataToMouseQueue(
                    437:                          &deviceExtension->MouseExtension,
                    438:                          &deviceExtension->MouseExtension.CurrentInput
                    439:                          )) {
                    440: 
                    441:                     //
                    442:                     // InputData queue overflowed.  
                    443:                     //
                    444:                     // Queue a DPC to log an overrun error.
                    445:                     //
                    446: 
                    447:                     I8xPrint((
                    448:                         1,
                    449:                         "I8042PRT-I8042MouseInterruptService: queue overflow\n"
                    450:                         ));
                    451: 
                    452:                     if (deviceExtension->MouseExtension.OkayToLogOverflow) {
                    453:                         KeInsertQueueDpc(
                    454:                             &deviceExtension->ErrorLogDpc,
                    455:                             (PIRP) NULL,
                    456:                             (PVOID) (ULONG) I8042_MOU_BUFFER_OVERFLOW
                    457:                             );
                    458:                         deviceExtension->MouseExtension.OkayToLogOverflow =
                    459:                             FALSE;
                    460:                     }
                    461: 
                    462:                 } else if (deviceExtension->DpcInterlockMouse >= 0) {
                    463:             
                    464:                    //
                    465:                    // The ISR DPC is already executing.  Tell the ISR DPC it has
                    466:                    // more work to do by incrementing DpcInterlockMouse.
                    467:                    //
                    468:             
                    469:                    deviceExtension->DpcInterlockMouse += 1;
                    470:             
                    471:                 } else {
                    472:             
                    473:                    //
                    474:                    // Queue the ISR DPC.
                    475:                    //
                    476:             
                    477:                    KeInsertQueueDpc(
                    478:                        &deviceExtension->MouseIsrDpc,
                    479:                        deviceObject->CurrentIrp,
                    480:                        NULL
                    481:                        );
                    482:                }
                    483:           
                    484:             }
                    485: 
                    486:             //
                    487:             // Reset the state.
                    488:             //
                    489: 
                    490:             deviceExtension->MouseExtension.InputState = MouseIdle;
                    491: 
                    492:             break;
                    493: 
                    494:         case MouseExpectingACK:
                    495: 
                    496:             //
                    497:             // This is a special case.  We hit this on one of the very 
                    498:             // first mouse interrupts following the IoConnectInterrupt.  
                    499:             // The interrupt is caused when we enable mouse transmissions
                    500:             // via I8xMouseEnableTransmission() -- the hardware returns
                    501:             // an ACK.  Just toss this byte away, and set the input state
                    502:             // to coincide with the start of a new mouse data packet.
                    503:             //
                    504: 
                    505:             I8xPrint((
                    506:                 1,
                    507:                 "I8042PRT-I8042MouseInterruptService: expecting ACK (0x%x), got 0x%x\n",
                    508:                 (ULONG) ACKNOWLEDGE,
                    509:                 (ULONG) byte
                    510:                 ));
                    511: 
                    512:             if (byte == (UCHAR) ACKNOWLEDGE) {
                    513:                 deviceExtension->MouseExtension.InputState = MouseIdle;
                    514:             } else if (byte == (UCHAR) RESEND) {
                    515:            
                    516:                 //
                    517:                 // Resend the "Enable Mouse Transmission" sequence.
                    518:                 // 
                    519:                 // NOTE: This is a hack for the Olivetti MIPS machine,
                    520:                 // which sends a resend response if a key is held down
                    521:                 // while we're attempting the I8xMouseEnableTransmission.
                    522:                 //
                    523: 
                    524:                 I8xPutByteAsynchronous(
                    525:                      (CCHAR) CommandPort,
                    526:                      deviceExtension,
                    527:                      (UCHAR) I8042_WRITE_TO_AUXILIARY_DEVICE
                    528:                      );
                    529: 
                    530:                 I8xPutByteAsynchronous(
                    531:                      (CCHAR) DataPort,
                    532:                      deviceExtension,
                    533:                      (UCHAR) ENABLE_MOUSE_TRANSMISSION
                    534:                      );
                    535:             }
                    536: 
                    537:             break;
                    538: 
                    539:         default:
                    540: 
                    541:             I8xPrint((
                    542:                 3,
                    543:                 "I8042PRT-I8042MouseInterruptService: INVALID STATE\n"
                    544:                 ));
                    545: 
                    546:             //
                    547:             // Queue a DPC to log an internal driver error.
                    548:             //
                    549: 
                    550:             KeInsertQueueDpc(
                    551:                 &deviceExtension->ErrorLogDpc,
                    552:                 (PIRP) NULL,
                    553:                 (PVOID) (ULONG) I8042_INVALID_ISR_STATE
                    554:                 );
                    555: 
                    556:             ASSERT(FALSE);
                    557:             break;
                    558: 
                    559:     }
                    560: 
                    561:     I8xPrint((2, "I8042PRT-I8042MouseInterruptService: exit\n"));
                    562: 
                    563:     return(TRUE);
                    564: }
                    565: 
                    566: NTSTATUS
                    567: I8xInitializeMouse(
                    568:     IN PDEVICE_OBJECT DeviceObject
                    569:     )
                    570: 
                    571: /*++
                    572: 
                    573: Routine Description:
                    574: 
                    575:     This routine initializes the i8042 mouse hardware.  It is called
                    576:     only at initialization, and does not synchronize access to the hardware.
                    577: 
                    578: Arguments:
                    579: 
                    580:     DeviceObject - Pointer to the device object.
                    581: 
                    582: Return Value:
                    583: 
                    584:     Returns status.
                    585: 
                    586: --*/
                    587: 
                    588: {
                    589:     NTSTATUS status;
                    590:     PDEVICE_EXTENSION deviceExtension;
                    591:     UCHAR byte;
                    592:     ULONG i;
                    593:     PIO_ERROR_LOG_PACKET errorLogEntry;
                    594:     ULONG uniqueErrorValue;
                    595:     NTSTATUS errorCode = STATUS_SUCCESS;
                    596:     ULONG dumpCount = 0;
                    597: 
                    598: #define DUMP_COUNT 4
                    599:     ULONG dumpData[DUMP_COUNT];
                    600: 
                    601:     I8xPrint((2, "I8042PRT-I8xInitializeMouse: enter\n"));
                    602: 
                    603:     for (i = 0; i < DUMP_COUNT; i++)
                    604:         dumpData[i] = 0;
                    605: 
                    606:     //
                    607:     // Get the device extension.
                    608:     //
                    609: 
                    610:     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
                    611: 
                    612:     //
                    613:     // Reset the mouse.  Send a Write To Auxiliary Device command to the
                    614:     // 8042 controller.  Then send the Reset Mouse command to the mouse
                    615:     // through the 8042 data register.  Expect to get back an ACK, followed
                    616:     // by a completion code and the ID code (0x00).
                    617:     //
                    618: 
                    619:     status = I8xPutBytePolled(
                    620:                  (CCHAR) DataPort,
                    621:                  WAIT_FOR_ACKNOWLEDGE,
                    622:                  (CCHAR) MouseDeviceType,
                    623:                  deviceExtension,
                    624:                  (UCHAR) MOUSE_RESET
                    625:                  );
                    626:     if (!NT_SUCCESS(status)) {
                    627:         I8xPrint((
                    628:             1,
                    629:             "I8042PRT-I8xInitializeMouse: failed mouse reset, status 0x%x\n",
                    630:             status
                    631:             ));
                    632: 
                    633:         //
                    634:         // Set up error log info.
                    635:         //
                    636:                     
                    637:         errorCode = I8042_MOU_RESET_COMMAND_FAILED;
                    638:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 415;
                    639:         dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
                    640:         dumpData[1] = DataPort;
                    641:         dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
                    642:         dumpData[3] = MOUSE_RESET;
                    643:         dumpCount = 4;
                    644:                 
                    645:         goto I8xInitializeMouseExit;
                    646:     }
                    647: 
                    648:     //
                    649:     // Get the mouse reset responses.  The first response should be a
                    650:     // MOUSE_COMPLETE.  The second response should be the mouse ID.
                    651:     // Note that it is usually necessary to stall a long time to get the
                    652:     // mouse reset/self-test to work.  The stall value was determined by
                    653:     // experimentation.
                    654:     //
                    655:     //
                    656: 
                    657:     for (i = 0; i < 11200; i++) {
                    658: 
                    659:         status = I8xGetBytePolled(
                    660:                      (CCHAR) ControllerDeviceType, 
                    661:                      deviceExtension, 
                    662:                      &byte
                    663:                      );
                    664: 
                    665:         if (NT_SUCCESS(status) && (byte == (UCHAR) MOUSE_COMPLETE)) {
                    666: 
                    667:             //
                    668:             // The reset completed successfully.
                    669:             //
                    670: 
                    671:             break;
                    672: 
                    673: 
                    674:         } else {
                    675: 
                    676:             //
                    677:             // Stall, and then try again to get a response from
                    678:             // the reset.
                    679:             //
                    680: 
                    681:             if (status == STATUS_IO_TIMEOUT) {
                    682: 
                    683:                 //
                    684:                 // Stall, and then try again to get a response from
                    685:                 // the reset.
                    686:                 //
                    687: 
                    688:                 KeStallExecutionProcessor(50);
                    689: 
                    690:             } else {
                    691: 
                    692:                 break;
                    693: 
                    694:             }
                    695:         }
                    696:     }
                    697: 
                    698:     if (!NT_SUCCESS(status)) {
                    699:         I8xPrint((
                    700:             1,
                    701:             "I8042PRT-I8xInitializeMouse: failed reset response 1, status 0x%x, byte 0x%x\n",
                    702:             status,
                    703:             byte
                    704:             ));
                    705: 
                    706:         //
                    707:         // Set up error log info.
                    708:         //
                    709: 
                    710:         errorCode = I8042_MOU_RESET_RESPONSE_FAILED;
                    711:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 420;
                    712:         dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
                    713:         dumpData[1] = ControllerDeviceType;
                    714:         dumpData[2] = MOUSE_COMPLETE;
                    715:         dumpData[3] = byte;
                    716:         dumpCount = 4;
                    717: 
                    718:         goto I8xInitializeMouseExit;
                    719:     }
                    720: 
                    721:     status = I8xGetBytePolled(
                    722:                  (CCHAR) ControllerDeviceType, 
                    723:                  deviceExtension, 
                    724:                  &byte
                    725:                  );
                    726: 
                    727:     if ((!NT_SUCCESS(status)) || (byte != MOUSE_ID_BYTE)) {
                    728:         I8xPrint((
                    729:             1,
                    730:             "I8042PRT-I8xInitializeMouse: failed reset response 2, status 0x%x, byte 0x%x\n",
                    731:             status,
                    732:             byte
                    733:             ));
                    734: 
                    735:         //
                    736:         // Set up error log info.
                    737:         //
                    738: 
                    739:         errorCode = I8042_MOU_RESET_RESPONSE_FAILED;
                    740:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 425;
                    741:         dumpData[0] = KBDMOU_INCORRECT_RESPONSE;
                    742:         dumpData[1] = ControllerDeviceType;
                    743:         dumpData[2] = MOUSE_ID_BYTE;
                    744:         dumpData[3] = byte;
                    745:         dumpCount = 4;
                    746:     
                    747:         goto I8xInitializeMouseExit;
                    748:     }
                    749: 
                    750:     //
                    751:     // Set mouse sampling rate.  Send a Write To Auxiliary Device command
                    752:     // to the 8042 controller.  Then send the Set Mouse Sampling Rate
                    753:     // command to the mouse through the 8042 data register,
                    754:     // followed by its parameter.
                    755:     //
                    756: 
                    757:     status = I8xPutBytePolled(
                    758:                  (CCHAR) DataPort,
                    759:                  WAIT_FOR_ACKNOWLEDGE,
                    760:                  (CCHAR) MouseDeviceType, 
                    761:                  deviceExtension,
                    762:                  (UCHAR) SET_MOUSE_SAMPLING_RATE
                    763:                  );
                    764:     if (!NT_SUCCESS(status)) {
                    765:         I8xPrint((
                    766:             1,
                    767:             "I8042PRT-I8xInitializeMouse: failed write set sample rate, status 0x%x\n",
                    768:             status
                    769:             ));
                    770: 
                    771:         //
                    772:         // Set up error log info.
                    773:         //
                    774:                     
                    775:         errorCode = I8042_SET_SAMPLE_RATE_FAILED;
                    776:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 435;
                    777:         dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
                    778:         dumpData[1] = DataPort;
                    779:         dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
                    780:         dumpData[3] = SET_MOUSE_SAMPLING_RATE;
                    781:         dumpCount = 4;
                    782:                 
                    783:         goto I8xInitializeMouseExit;
                    784:     }
                    785: 
                    786:     status = I8xPutBytePolled(
                    787:                  (CCHAR) DataPort,
                    788:                  WAIT_FOR_ACKNOWLEDGE,
                    789:                  (CCHAR) MouseDeviceType, 
                    790:                  deviceExtension,
                    791:                  (UCHAR) MOUSE_SAMPLE_RATE
                    792:                  );
                    793:     if (!NT_SUCCESS(status)) {
                    794:         I8xPrint((
                    795:             1,
                    796:             "I8042PRT-I8xInitializeMouse: failed write sample rate, status 0x%x\n",
                    797:             status
                    798:             ));
                    799: 
                    800:         //
                    801:         // Set up error log info.
                    802:         //
                    803:         
                    804:         errorCode = I8042_SET_SAMPLE_RATE_FAILED;
                    805:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 445;
                    806:         dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
                    807:         dumpData[1] = DataPort;
                    808:         dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
                    809:         dumpData[3] = MOUSE_SAMPLE_RATE;
                    810:         dumpCount = 4;
                    811:                 
                    812:         goto I8xInitializeMouseExit;
                    813:     }
                    814: 
                    815:     //
                    816:     // Set the mouse resolution.  Send a Write To Auxiliary Device command
                    817:     // to the 8042 controller.  Then send the Set Mouse Resolution
                    818:     // command to the mouse through the 8042 data register,
                    819:     // followed by its parameter.
                    820:     //
                    821: 
                    822:     status = I8xPutBytePolled(
                    823:                  (CCHAR) DataPort,
                    824:                  WAIT_FOR_ACKNOWLEDGE,
                    825:                  (CCHAR) MouseDeviceType, 
                    826:                  deviceExtension,
                    827:                  (UCHAR) SET_MOUSE_RESOLUTION
                    828:                  );
                    829:     if (!NT_SUCCESS(status)) {
                    830:         I8xPrint((
                    831:             1,
                    832:             "I8042PRT-I8xInitializeMouse: failed write set resolution, status 0x%x\n",
                    833:             status
                    834:             ));
                    835: 
                    836:         //
                    837:         // Set up error log info.
                    838:         //
                    839:                     
                    840:         errorCode = I8042_SET_RESOLUTION_FAILED;
                    841:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 455;
                    842:         dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
                    843:         dumpData[1] = DataPort;
                    844:         dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
                    845:         dumpData[3] = SET_MOUSE_RESOLUTION;
                    846:         dumpCount = 4;
                    847:                 
                    848:         goto I8xInitializeMouseExit;
                    849:     }
                    850: 
                    851:     status = I8xPutBytePolled(
                    852:                  (CCHAR) DataPort,
                    853:                  WAIT_FOR_ACKNOWLEDGE,
                    854:                  (CCHAR) MouseDeviceType, 
                    855:                  deviceExtension,
                    856:                  (UCHAR) deviceExtension->Configuration.MouseResolution
                    857:                  );
                    858:     if (!NT_SUCCESS(status)) {
                    859:         I8xPrint((
                    860:             1,
                    861:             "I8042PRT-I8xInitializeMouse: failed set mouse resolution, status 0x%x\n",
                    862:             status
                    863:             ));
                    864: 
                    865:         //
                    866:         // Set up error log info.
                    867:         //
                    868:                     
                    869:         errorCode = I8042_SET_RESOLUTION_FAILED;
                    870:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 465;
                    871:         dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
                    872:         dumpData[1] = DataPort;
                    873:         dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
                    874:         dumpData[3] = deviceExtension->Configuration.MouseResolution;
                    875:         dumpCount = 4;
                    876:                 
                    877:         goto I8xInitializeMouseExit;
                    878:     }
                    879: 
                    880: I8xInitializeMouseExit:
                    881: 
                    882:     if (!NT_SUCCESS(status)) {
                    883: 
                    884:         //
                    885:         // The mouse initialization failed.  Log an error.
                    886:         //
                    887: 
                    888:         if (errorCode != STATUS_SUCCESS) {
                    889:             errorLogEntry = (PIO_ERROR_LOG_PACKET)
                    890:                 IoAllocateErrorLogEntry(
                    891:                     DeviceObject,
                    892:                     (UCHAR) (sizeof(IO_ERROR_LOG_PACKET) 
                    893:                              + (dumpCount * sizeof(ULONG)))
                    894:                     );
                    895:     
                    896:             if (errorLogEntry != NULL) {
                    897:     
                    898:                 errorLogEntry->ErrorCode = errorCode;
                    899:                 errorLogEntry->DumpDataSize = dumpCount * sizeof(ULONG);
                    900:                 errorLogEntry->SequenceNumber = 0;
                    901:                 errorLogEntry->MajorFunctionCode = 0;
                    902:                 errorLogEntry->IoControlCode = 0;
                    903:                 errorLogEntry->RetryCount = 0;
                    904:                 errorLogEntry->UniqueErrorValue = uniqueErrorValue;
                    905:                 errorLogEntry->FinalStatus = status;
                    906:                 for (i = 0; i < dumpCount; i++)
                    907:                     errorLogEntry->DumpData[i] = dumpData[i];
                    908:     
                    909:                 IoWriteErrorLogEntry(errorLogEntry);
                    910:             }
                    911:         }
                    912:     }
                    913: 
                    914:     //
                    915:     // Initialize current mouse input packet state.
                    916:     //
                    917: 
                    918:     deviceExtension->MouseExtension.PreviousSignAndOverflow = 0;
                    919:     deviceExtension->MouseExtension.InputState = MouseExpectingACK;
                    920: 
                    921:     I8xPrint((2, "I8042PRT-I8xInitializeMouse: exit\n"));
                    922: 
                    923:     return(status);
                    924: }
                    925: 
                    926: VOID
                    927: I8xMouseConfiguration(
                    928:     IN PDEVICE_EXTENSION DeviceExtension,
                    929:     IN PUNICODE_STRING RegistryPath,
                    930:     IN PUNICODE_STRING KeyboardDeviceName,
                    931:     IN PUNICODE_STRING PointerDeviceName
                    932:     )
                    933: 
                    934: /*++
                    935: 
                    936: Routine Description:
                    937: 
                    938:     This routine retrieves the configuration information for the mouse.
                    939: 
                    940: Arguments:
                    941: 
                    942:     DeviceExtension - Pointer to the device extension.
                    943: 
                    944:     RegistryPath - Pointer to the null-terminated Unicode name of the 
                    945:         registry path for this driver.
                    946: 
                    947:     KeyboardDeviceName - Pointer to the Unicode string that will receive
                    948:         the keyboard port device name.
                    949: 
                    950:     PointerDeviceName - Pointer to the Unicode string that will receive
                    951:         the pointer port device name.
                    952: 
                    953: 
                    954: Return Value:
                    955: 
                    956:     None.  As a side-effect, may set DeviceExtension->HardwarePresent.
                    957: 
                    958: --*/
                    959: {
                    960:     NTSTATUS status = STATUS_SUCCESS;
                    961:     INTERFACE_TYPE interfaceType;
                    962:     CONFIGURATION_TYPE controllerType = PointerController;
                    963:     CONFIGURATION_TYPE peripheralType = PointerPeripheral;
                    964:     ULONG i;
                    965: 
                    966:     for (i = 0; i < MaximumInterfaceType; i++) {
                    967:  
                    968:         //
                    969:         // Get the registry information for this device.
                    970:         //
                    971: 
                    972:         interfaceType = i;
                    973:         status = IoQueryDeviceDescription(&interfaceType,
                    974:                                           NULL,
                    975:                                           &controllerType,
                    976:                                           NULL,
                    977:                                           &peripheralType,
                    978:                                           NULL,
                    979:                                           I8xMousePeripheralCallout,
                    980:                                           (PVOID) DeviceExtension);
                    981:     
                    982:         if (DeviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) {
                    983:     
                    984:             //
                    985:             // If we didn't already get these when determining the keyboard
                    986:             // configuration, get the service parameters now (e.g., 
                    987:             // user-configurable number of resends, polling iterations, etc.).
                    988:             //
                    989: 
                    990:             if (!(DeviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT))
                    991:                 I8xServiceParameters(
                    992:                     DeviceExtension, 
                    993:                     RegistryPath, 
                    994:                     KeyboardDeviceName,
                    995:                     PointerDeviceName
                    996:                     );
                    997:         
                    998:             //
                    999:             // Initialize mouse-specific configuration parameters.
                   1000:             //
                   1001:         
                   1002:             DeviceExtension->Configuration.MouseAttributes.MouseIdentifier =
                   1003:                 MOUSE_I8042_HARDWARE;
                   1004:     
                   1005:             break;
                   1006:     
                   1007:         } else {
                   1008:             I8xPrint((
                   1009:                 1, 
                   1010:                 "I8042PRT-I8xMouseConfiguration: IoQueryDeviceDescription for bus type %d failed\n",
                   1011:                 interfaceType
                   1012:                 ));
                   1013:         }
                   1014:     }
                   1015: }
                   1016: 
                   1017: NTSTATUS
                   1018: I8xMouseEnableTransmission(
                   1019:     IN PDEVICE_OBJECT DeviceObject
                   1020:     )
                   1021: 
                   1022: /*++
                   1023: 
                   1024: Routine Description:
                   1025: 
                   1026:     This routine sends an Enable command to the mouse hardware, causing
                   1027:     the mouse to begin transmissions.  It is called at initialization
                   1028:     time, but only after the interrupt has been connected.  This is 
                   1029:     necessary so the driver can keep its notion of the mouse input data 
                   1030:     state in sync with the hardware (i.e., for this type of mouse there is no
                   1031:     way to differentiate the first byte of a packet; if the user is randomly
                   1032:     moving the mouse during boot/initialization, the first mouse interrupt we
                   1033:     receive following IoConnectInterrupt could be for a byte that is not the 
                   1034:     start of a packet, and we have no way to know that).
                   1035: 
                   1036: Arguments:
                   1037: 
                   1038:     DeviceObject - Pointer to the device object.
                   1039: 
                   1040: Return Value:
                   1041: 
                   1042:     Returns status.
                   1043: 
                   1044: --*/
                   1045: 
                   1046: {
                   1047:     NTSTATUS status;
                   1048:     PDEVICE_EXTENSION deviceExtension;
                   1049:     PIO_ERROR_LOG_PACKET errorLogEntry;
                   1050:     ULONG uniqueErrorValue;
                   1051:     NTSTATUS errorCode = STATUS_SUCCESS;
                   1052:     ULONG i;
                   1053:     ULONG dumpCount = 0;
                   1054: 
                   1055: #define DUMP_COUNT 4
                   1056:     ULONG dumpData[DUMP_COUNT];
                   1057: 
                   1058:     I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: enter\n"));
                   1059: 
                   1060:     for (i = 0; i < DUMP_COUNT; i++)
                   1061:         dumpData[i] = 0;
                   1062: 
                   1063:     //
                   1064:     // Get the device extension.
                   1065:     //
                   1066: 
                   1067:     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
                   1068: 
                   1069:     //
                   1070:     // Re-enable the mouse at the mouse hardware, so that it can transmit
                   1071:     // data packets in continuous mode.  Note that this is not the same
                   1072:     // as enabling the mouse device at the 8042 controller.  The mouse
                   1073:     // hardware is sent an Enable command here, because it was
                   1074:     // Disabled as a result of the mouse reset command performed 
                   1075:     // in I8xInitializeMouse().
                   1076:     //
                   1077:     // Note that we don't wait for an ACKNOWLEDGE back.  The
                   1078:     // ACKNOWLEDGE back will actually cause a mouse interrupt, which 
                   1079:     // then gets handled in the mouse ISR.
                   1080:     //
                   1081: 
                   1082:     status = I8xPutBytePolled(
                   1083:                  (CCHAR) DataPort,
                   1084:                  NO_WAIT_FOR_ACKNOWLEDGE,
                   1085:                  (CCHAR) MouseDeviceType, 
                   1086:                  deviceExtension,
                   1087:                  (UCHAR) ENABLE_MOUSE_TRANSMISSION
                   1088:                  );
                   1089:     if (!NT_SUCCESS(status)) {
                   1090:         I8xPrint((
                   1091:             1,
                   1092:             "I8042PRT-I8xMouseEnableTransmission: failed write enable transmission, status 0x%x\n",
                   1093:             status
                   1094:             ));
                   1095: 
                   1096:         //
                   1097:         // Set up error log info.
                   1098:         //
                   1099:                 
                   1100:         errorCode = I8042_MOU_ENABLE_XMIT;
                   1101:         uniqueErrorValue = I8042_ERROR_VALUE_BASE + 475;
                   1102:         dumpData[0] = KBDMOU_COULD_NOT_SEND_PARAM;
                   1103:         dumpData[1] = DataPort;
                   1104:         dumpData[2] = I8042_WRITE_TO_AUXILIARY_DEVICE;
                   1105:         dumpData[3] = ENABLE_MOUSE_TRANSMISSION;
                   1106:         dumpCount = 4;
                   1107:             
                   1108:     }
                   1109: 
                   1110:     I8xPrint((2, "I8042PRT-I8xMouseEnableTransmission: exit\n"));
                   1111: 
                   1112:     return(status);
                   1113: }
                   1114: 
                   1115: NTSTATUS 
                   1116: I8xMousePeripheralCallout(
                   1117:     IN PVOID Context,
                   1118:     IN PUNICODE_STRING PathName,
                   1119:     IN INTERFACE_TYPE BusType,
                   1120:     IN ULONG BusNumber,
                   1121:     IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
                   1122:     IN CONFIGURATION_TYPE ControllerType,
                   1123:     IN ULONG ControllerNumber,
                   1124:     IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
                   1125:     IN CONFIGURATION_TYPE PeripheralType,
                   1126:     IN ULONG PeripheralNumber,
                   1127:     IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
                   1128:     )
                   1129: 
                   1130: /*++
                   1131: 
                   1132: Routine Description:
                   1133: 
                   1134:     This is the callout routine sent as a parameter to 
                   1135:     IoQueryDeviceDescription.  It grabs the pointer controller and
                   1136:     peripheral configuration information.
                   1137: 
                   1138: Arguments:
                   1139: 
                   1140:     Context - Context parameter that was passed in by the routine
                   1141:         that called IoQueryDeviceDescription.
                   1142: 
                   1143:     PathName - The full pathname for the registry key.
                   1144: 
                   1145:     BusType - Bus interface type (Isa, Eisa, Mca, etc.).
                   1146: 
                   1147:     BusNumber - The bus sub-key (0, 1, etc.).
                   1148: 
                   1149:     BusInformation - Pointer to the array of pointers to the full value 
                   1150:         information for the bus.
                   1151: 
                   1152:     ControllerType - The controller type (should be PointerController).
                   1153: 
                   1154:     ControllerNumber - The controller sub-key (0, 1, etc.).
                   1155: 
                   1156:     ControllerInformation - Pointer to the array of pointers to the full 
                   1157:         value information for the controller key.
                   1158: 
                   1159:     PeripheralType - The peripheral type (should be PointerPeripheral).
                   1160: 
                   1161:     PeripheralNumber - The peripheral sub-key.
                   1162: 
                   1163:     PeripheralInformation - Pointer to the array of pointers to the full 
                   1164:         value information for the peripheral key.
                   1165:     
                   1166: 
                   1167: Return Value:
                   1168: 
                   1169:     None.  If successful, will have the following side-effects:
                   1170: 
                   1171:         - Sets DeviceObject->DeviceExtension->HardwarePresent.
                   1172:         - Sets configuration fields in 
                   1173:           DeviceObject->DeviceExtension->Configuration.
                   1174: 
                   1175: --*/
                   1176: {
                   1177:     PDEVICE_EXTENSION deviceExtension;
                   1178:     PI8042_CONFIGURATION_INFORMATION configuration;
                   1179:     UNICODE_STRING unicodeIdentifier;
                   1180:     ANSI_STRING ansiString;
                   1181:     PUCHAR controllerData;
                   1182:     NTSTATUS status = STATUS_SUCCESS;
                   1183:     ULONG i;
                   1184:     ULONG listCount;
                   1185:     PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor;
                   1186:     CM_PARTIAL_RESOURCE_DESCRIPTOR tmpResourceDescriptor;
                   1187:     BOOLEAN portInfoNeeded;
                   1188:     BOOLEAN defaultInterruptShare;
                   1189:     KINTERRUPT_MODE defaultInterruptMode; 
                   1190:  
                   1191:     I8xPrint((
                   1192:         1, 
                   1193:         "I8042PRT-I8xMousePeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n",
                   1194:         PathName, BusType, BusNumber 
                   1195:         ));
                   1196:     I8xPrint((
                   1197:         1, 
                   1198:         "    Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n",
                   1199:         ControllerType, ControllerNumber, ControllerInformation
                   1200:         ));
                   1201:     I8xPrint((
                   1202:         1, 
                   1203:         "    Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n",
                   1204:         PeripheralType, PeripheralNumber, PeripheralInformation
                   1205:         ));
                   1206: 
                   1207:     //
                   1208:     // Get the length of the peripheral identifier information.
                   1209:     //
                   1210: 
                   1211:     unicodeIdentifier.Length =
                   1212:         (*(PeripheralInformation + IoQueryDeviceIdentifier))->DataLength;
                   1213: 
                   1214:     //
                   1215:     // If we already have the configuration information for the
                   1216:     // pointer peripheral, or if the peripheral identifier is missing, 
                   1217:     // just return.
                   1218:     //
                   1219: 
                   1220:     deviceExtension = (PDEVICE_EXTENSION) Context;
                   1221:     if ((deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT) 
                   1222:          || (unicodeIdentifier.Length == 0)) {
                   1223:         return (status);
                   1224:     }
                   1225: 
                   1226:     configuration = &deviceExtension->Configuration;
                   1227: 
                   1228:     //
                   1229:     // Get the identifier information for the peripheral.
                   1230:     //
                   1231: 
                   1232:     unicodeIdentifier.MaximumLength = unicodeIdentifier.Length;
                   1233:     unicodeIdentifier.Buffer = (PWSTR) (((PUCHAR)(*(PeripheralInformation +
                   1234:                                IoQueryDeviceIdentifier))) +
                   1235:                                (*(PeripheralInformation + 
                   1236:                                IoQueryDeviceIdentifier))->DataOffset);
                   1237:     I8xPrint((
                   1238:         1,
                   1239:         "I8042PRT-I8xMousePeripheralCallout: Mouse type %ws\n",
                   1240:         unicodeIdentifier.Buffer));
                   1241: 
                   1242:     //
                   1243:     // Verify that this is an i8042 mouse.
                   1244:     //
                   1245: 
                   1246:     status = RtlUnicodeStringToAnsiString(
                   1247:                  &ansiString,
                   1248:                  &unicodeIdentifier,
                   1249:                  TRUE
                   1250:                  );
                   1251: 
                   1252:     if (!NT_SUCCESS(status)) {
                   1253:         I8xPrint((
                   1254:             1,
                   1255:             "I8042PRT-I8xMousePeripheralCallout: Could not convert identifier to Ansi\n"
                   1256:             ));
                   1257:         return(status);
                   1258:     }
                   1259:  
                   1260:     if (strstr(ansiString.Buffer, "PS2")) {
                   1261: 
                   1262:          //
                   1263:          // There is a mouse on the i8042 controller.
                   1264:          //
                   1265: 
                   1266:          deviceExtension->HardwarePresent |= MOUSE_HARDWARE_PRESENT;
                   1267:     }
                   1268:    
                   1269:     RtlFreeAnsiString(&ansiString);
                   1270: 
                   1271:     if (!(deviceExtension->HardwarePresent & MOUSE_HARDWARE_PRESENT)) {
                   1272:         return(status);
                   1273:     }
                   1274: 
                   1275:     if (!(deviceExtension->HardwarePresent & KEYBOARD_HARDWARE_PRESENT)) {
                   1276: 
                   1277:         //
                   1278:         // If we don't already have the bus information as the result
                   1279:         // of the keyboard configuration, grab it now.
                   1280:         //
                   1281: 
                   1282:         configuration->InterfaceType = BusType;
                   1283:         configuration->BusNumber = BusNumber;
                   1284:         configuration->FloatingSave = I8042_FLOATING_SAVE;
                   1285:     }
                   1286: 
                   1287:     if (configuration->InterfaceType == MicroChannel) {
                   1288:         defaultInterruptShare = TRUE;
                   1289:         defaultInterruptMode = LevelSensitive;
                   1290:     } else {
                   1291:         defaultInterruptShare = I8042_INTERRUPT_SHARE;
                   1292:         defaultInterruptMode = I8042_INTERRUPT_MODE;
                   1293:     }
                   1294: 
                   1295:     //
                   1296:     // Look through the controller's resource list for interrupt 
                   1297:     // and (possibly) port configuration information.
                   1298:     //
                   1299:     
                   1300:     if ((*(ControllerInformation + IoQueryDeviceConfigurationData))->DataLength != 0){
                   1301:         controllerData = ((PUCHAR) (*(ControllerInformation +
                   1302:                                    IoQueryDeviceConfigurationData))) +
                   1303:                                    (*(ControllerInformation +
                   1304:                                    IoQueryDeviceConfigurationData))->DataOffset;
                   1305:     
                   1306:         controllerData += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, 
                   1307:                                        PartialResourceList);
                   1308:     
                   1309:         listCount = ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->Count;
                   1310:     
                   1311:         resourceDescriptor = 
                   1312:             ((PCM_PARTIAL_RESOURCE_LIST) controllerData)->PartialDescriptors;
                   1313:     
                   1314:         portInfoNeeded = configuration->PortListCount? FALSE:TRUE;
                   1315:         
                   1316:         for (i = 0; i < listCount; i++, resourceDescriptor++) {
                   1317:             switch(resourceDescriptor->Type) {
                   1318:                 case CmResourceTypePort:
                   1319:     
                   1320:                     if (portInfoNeeded) {
                   1321:     
                   1322:                         //
                   1323:                         // If we don't already have the port information as
                   1324:                         // a result of the keyboard configuration, copy it
                   1325:                         // to the port list.
                   1326:                         //
                   1327:     
                   1328:                         configuration->PortList[configuration->PortListCount] =
                   1329:                             *resourceDescriptor;
                   1330:                         configuration->PortList[configuration->PortListCount].ShareDisposition =
                   1331:                             I8042_REGISTER_SHARE? CmResourceShareShared:
                   1332:                                                   CmResourceShareDriverExclusive;
                   1333:                         configuration->PortListCount += 1;
                   1334:              
                   1335:                     }
                   1336:     
                   1337:                     break;
                   1338:         
                   1339:                 case CmResourceTypeInterrupt:
                   1340:     
                   1341:                     //
                   1342:                     // Copy the interrupt information.
                   1343:                     //
                   1344:     
                   1345:                     configuration->MouseInterrupt = *resourceDescriptor;
                   1346:                     configuration->MouseInterrupt.ShareDisposition = 
                   1347:                         defaultInterruptShare? CmResourceShareShared : 
                   1348:                                                CmResourceShareDeviceExclusive;
                   1349:     
                   1350:                     break;
                   1351:         
                   1352:                 default:
                   1353:                     break;
                   1354:             }
                   1355:         }
                   1356:     }
                   1357:     
                   1358:     //
                   1359:     // If no interrupt configuration information was found, use the
                   1360:     // mouse driver defaults.
                   1361:     //
                   1362:     
                   1363:     if (!(configuration->MouseInterrupt.Type & CmResourceTypeInterrupt)) {
                   1364:     
                   1365:         I8xPrint((
                   1366:             1,
                   1367:             "I8042PRT-I8xMousePeripheralCallout: Using default mouse interrupt config\n"
                   1368:             ));
                   1369: 
                   1370:         configuration->MouseInterrupt.Type = CmResourceTypeInterrupt;
                   1371:         configuration->MouseInterrupt.ShareDisposition = 
                   1372:             defaultInterruptShare? CmResourceShareShared : 
                   1373:                                    CmResourceShareDeviceExclusive;
                   1374:         configuration->MouseInterrupt.Flags = 
                   1375:             (defaultInterruptMode == Latched)? CM_RESOURCE_INTERRUPT_LATCHED :
                   1376:                 CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
                   1377:         configuration->MouseInterrupt.u.Interrupt.Level = MOUSE_IRQL;
                   1378:         configuration->MouseInterrupt.u.Interrupt.Vector = MOUSE_VECTOR;
                   1379:     }
                   1380:     
                   1381:     I8xPrint((
                   1382:         1,
                   1383:         "I8042PRT-I8xMousePeripheralCallout: Mouse interrupt config --\n"
                   1384:         ));
                   1385:     I8xPrint((
                   1386:         1,
                   1387:         "%s, %s, Irq = %d\n",
                   1388:         configuration->MouseInterrupt.ShareDisposition == CmResourceShareShared? 
                   1389:             "Sharable" : "NonSharable",
                   1390:         configuration->MouseInterrupt.Flags == CM_RESOURCE_INTERRUPT_LATCHED?
                   1391:             "Latched" : "Level Sensitive",
                   1392:         configuration->MouseInterrupt.u.Interrupt.Vector
                   1393:         ));
                   1394:     
                   1395:     //
                   1396:     // If no port configuration information was found, use the
                   1397:     // mouse driver defaults.
                   1398:     //
                   1399:     
                   1400:     if (configuration->PortListCount == 0) {
                   1401:     
                   1402:         //
                   1403:         // No port configuration information was found, so use 
                   1404:         // the driver defaults.
                   1405:         //
                   1406:     
                   1407:         I8xPrint((
                   1408:             1,
                   1409:             "I8042PRT-I8xMousePeripheralCallout: Using default port config\n"
                   1410:             ));
                   1411: 
                   1412:         configuration->PortList[DataPort].Type = CmResourceTypePort;
                   1413:         configuration->PortList[DataPort].Flags = I8042_PORT_TYPE;
                   1414:         configuration->PortList[DataPort].ShareDisposition = 
                   1415:             I8042_REGISTER_SHARE? CmResourceShareShared:
                   1416:                                   CmResourceShareDriverExclusive;
                   1417:         configuration->PortList[DataPort].u.Port.Start.LowPart = 
                   1418:             I8042_PHYSICAL_BASE + I8042_DATA_REGISTER_OFFSET;
                   1419:         configuration->PortList[DataPort].u.Port.Start.HighPart = 0;
                   1420:         configuration->PortList[DataPort].u.Port.Length = I8042_REGISTER_LENGTH;
                   1421:     
                   1422:         configuration->PortList[CommandPort].Type = CmResourceTypePort;
                   1423:         configuration->PortList[CommandPort].Flags = I8042_PORT_TYPE;
                   1424:         configuration->PortList[CommandPort].ShareDisposition = 
                   1425:             I8042_REGISTER_SHARE? CmResourceShareShared:
                   1426:                                   CmResourceShareDriverExclusive;
                   1427:         configuration->PortList[CommandPort].u.Port.Start.LowPart = 
                   1428:             I8042_PHYSICAL_BASE + I8042_COMMAND_REGISTER_OFFSET;
                   1429:         configuration->PortList[CommandPort].u.Port.Start.HighPart = 0;
                   1430:         configuration->PortList[CommandPort].u.Port.Length = I8042_REGISTER_LENGTH;
                   1431: 
                   1432:         configuration->PortListCount = 2;
                   1433:     } else if (configuration->PortListCount == 1) {
                   1434: 
                   1435:         //
                   1436:         // Kludge for Jazz machines.  Their ARC firmware neglects to 
                   1437:         // separate out the port addresses, so fix that up here.
                   1438:         //
                   1439:         
                   1440:         configuration->PortList[CommandPort] = configuration->PortList[DataPort];
                   1441:         configuration->PortList[CommandPort].u.Port.Start.LowPart += 
                   1442:             I8042_COMMAND_REGISTER_OFFSET;
                   1443:         configuration->PortListCount += 1;
                   1444:     } else {
                   1445:     
                   1446:         //
                   1447:         // Put the lowest port address range in the DataPort element of 
                   1448:         // the port list.
                   1449:         //
                   1450:     
                   1451:         if (configuration->PortList[CommandPort].u.Port.Start.LowPart 
                   1452:             < configuration->PortList[DataPort].u.Port.Start.LowPart) {
                   1453:                tmpResourceDescriptor = configuration->PortList[DataPort];
                   1454:                configuration->PortList[DataPort] = 
                   1455:                    configuration->PortList[CommandPort];
                   1456:                configuration->PortList[CommandPort] = tmpResourceDescriptor;
                   1457:         }
                   1458:     }
                   1459: 
                   1460:     for (i = 0; i < configuration->PortListCount; i++) {
                   1461: 
                   1462:         I8xPrint((
                   1463:             1,
                   1464:             "    %s, Ports 0x%x - 0x%x\n",
                   1465:             configuration->PortList[i].ShareDisposition 
                   1466:                 == CmResourceShareShared?  "Sharable" : "NonSharable",
                   1467:             configuration->PortList[i].u.Port.Start.LowPart,
                   1468:             configuration->PortList[i].u.Port.Start.LowPart +
                   1469:                 configuration->PortList[i].u.Port.Length - 1
                   1470:             ));
                   1471:     }
                   1472: 
                   1473:     return(status);
                   1474: }

unix.superglobalmegacorp.com

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