Annotation of ntddk/src/input/i8042prt/moudep.c, revision 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.