Annotation of ntddk/src/input/sermouse/sermcmn.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990, 1991, 1992, 1993  Microsoft Corporation
        !             4: Copyright (c) 1993  Logitech Inc.
        !             5: 
        !             6: Module Name:
        !             7: 
        !             8:     sermcmn.c
        !             9: 
        !            10: Abstract:
        !            11: 
        !            12:     The common portions of the Microsoft serial (i8250) mouse port driver.
        !            13:     This file should not require modification to support new mice
        !            14:     that are similar to the serial mouse.
        !            15: 
        !            16: Environment:
        !            17: 
        !            18:     Kernel mode only.
        !            19: 
        !            20: Notes:
        !            21: 
        !            22:     NOTES:  (Future/outstanding issues)
        !            23: 
        !            24:     - Powerfail not implemented.
        !            25: 
        !            26:     - IOCTL_INTERNAL_MOUSE_DISCONNECT has not been implemented.  It's not
        !            27:       needed until the class unload routine is implemented. Right now,
        !            28:       we don't want to allow the mouse class driver to unload.
        !            29: 
        !            30:     - Consolidate duplicate code, where possible and appropriate.
        !            31: 
        !            32: Revision History:
        !            33: 
        !            34: 
        !            35: --*/
        !            36: 
        !            37: #include "stdarg.h"
        !            38: #include "stdio.h"
        !            39: #include "string.h"
        !            40: #include "ntddk.h"
        !            41: #include "sermouse.h"
        !            42: #include "sermlog.h"
        !            43: #include "debug.h"
        !            44: 
        !            45: 
        !            46: VOID
        !            47: SerialMouseErrorLogDpc(
        !            48:     IN PKDPC Dpc,
        !            49:     IN PDEVICE_OBJECT DeviceObject,
        !            50:     IN PIRP Irp,
        !            51:     IN PVOID Context
        !            52:     )
        !            53: 
        !            54: /*++
        !            55: 
        !            56: Routine Description:
        !            57: 
        !            58:     This routine runs at DISPATCH_LEVEL IRQL to log errors that are
        !            59:     discovered at IRQL > DISPATCH_LEVEL (e.g., in the ISR routine or
        !            60:     in a routine that is executed via KeSynchronizeExecution).  There
        !            61:     is not necessarily a current request associated with this condition.
        !            62: 
        !            63: Arguments:
        !            64: 
        !            65:     Dpc - Pointer to the DPC object.
        !            66: 
        !            67:     DeviceObject - Pointer to the device object.
        !            68: 
        !            69:     Irp - Not used.
        !            70: 
        !            71:     Context - Indicates type of error to log.
        !            72: 
        !            73: Return Value:
        !            74: 
        !            75:     None.
        !            76: 
        !            77: --*/
        !            78: 
        !            79: {
        !            80:     PDEVICE_EXTENSION deviceExtension;
        !            81:     PIO_ERROR_LOG_PACKET errorLogEntry;
        !            82: 
        !            83:     UNREFERENCED_PARAMETER(Dpc);
        !            84:     UNREFERENCED_PARAMETER(Irp);
        !            85: 
        !            86:     SerMouPrint((2, "SERMOUSE-SerialMouseErrorLogDpc: enter\n"));
        !            87: 
        !            88:     deviceExtension = DeviceObject->DeviceExtension;
        !            89: 
        !            90:     //
        !            91:     // Log an error packet.
        !            92:     //
        !            93: 
        !            94:     errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
        !            95:                                               DeviceObject,
        !            96:                                               sizeof(IO_ERROR_LOG_PACKET)
        !            97:                                               + (2 * sizeof(ULONG))
        !            98:                                               );
        !            99:     if (errorLogEntry != NULL) {
        !           100: 
        !           101:         errorLogEntry->DumpDataSize = 2 * sizeof(ULONG);
        !           102: 
        !           103:         if ((ULONG) Context == SERMOUSE_MOU_BUFFER_OVERFLOW) {
        !           104:             errorLogEntry->UniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 210;
        !           105:             errorLogEntry->DumpData[0] = sizeof(MOUSE_INPUT_DATA);
        !           106:             errorLogEntry->DumpData[1] =
        !           107:                 deviceExtension->Configuration.MouseAttributes.InputDataQueueLength;
        !           108:         } else {
        !           109:             errorLogEntry->UniqueErrorValue = SERIAL_MOUSE_ERROR_VALUE_BASE + 220;
        !           110:             errorLogEntry->DumpData[0] = 0;
        !           111:             errorLogEntry->DumpData[1] = 0;
        !           112:         }
        !           113: 
        !           114:         errorLogEntry->ErrorCode = (ULONG) Context;
        !           115:         errorLogEntry->SequenceNumber = 0;
        !           116:         errorLogEntry->MajorFunctionCode = 0;
        !           117:         errorLogEntry->IoControlCode = 0;
        !           118:         errorLogEntry->RetryCount = 0;
        !           119:         errorLogEntry->FinalStatus = 0;
        !           120: 
        !           121:         IoWriteErrorLogEntry(errorLogEntry);
        !           122:     }
        !           123: 
        !           124:     SerMouPrint((2, "SERMOUSE-SerialMouseErrorLogDpc: exit\n"));
        !           125: 
        !           126: }
        !           127: 
        !           128: NTSTATUS
        !           129: SerialMouseFlush(
        !           130:     IN PDEVICE_OBJECT DeviceObject,
        !           131:     IN PIRP Irp
        !           132:     )
        !           133: {
        !           134:     UNREFERENCED_PARAMETER(DeviceObject);
        !           135:     UNREFERENCED_PARAMETER(Irp);
        !           136: 
        !           137:     SerMouPrint((2,"SERMOUSE-SerialMouseFlush: enter\n"));
        !           138:     SerMouPrint((2,"SERMOUSE-SerialMouseFlush: exit\n"));
        !           139: 
        !           140:     return(STATUS_NOT_IMPLEMENTED);
        !           141: }
        !           142: 
        !           143: NTSTATUS
        !           144: SerialMouseInternalDeviceControl(
        !           145:     IN PDEVICE_OBJECT DeviceObject,
        !           146:     IN PIRP Irp
        !           147:     )
        !           148: 
        !           149: /*++
        !           150: 
        !           151: Routine Description:
        !           152: 
        !           153:     This routine is the dispatch routine for internal device control requests.
        !           154: 
        !           155: Arguments:
        !           156: 
        !           157:     DeviceObject - Pointer to the device object.
        !           158: 
        !           159:     Irp - Pointer to the request packet.
        !           160: 
        !           161: Return Value:
        !           162: 
        !           163:     Status is returned.
        !           164: 
        !           165: --*/
        !           166: 
        !           167: {
        !           168: 
        !           169:     PIO_STACK_LOCATION irpSp;
        !           170:     PDEVICE_EXTENSION deviceExtension;
        !           171:     NTSTATUS status;
        !           172: 
        !           173:     SerMouPrint((2,"SERMOUSE-SerialMouseInternalDeviceControl: enter\n"));
        !           174: 
        !           175:     //
        !           176:     // Get a pointer to the device extension.
        !           177:     //
        !           178: 
        !           179:     deviceExtension = DeviceObject->DeviceExtension;
        !           180: 
        !           181:     //
        !           182:     // Initialize the returned Information field.
        !           183:     //
        !           184: 
        !           185:     Irp->IoStatus.Information = 0;
        !           186: 
        !           187:     //
        !           188:     // Get a pointer to the current parameters for this request.  The
        !           189:     // information is contained in the current stack location.
        !           190:     //
        !           191: 
        !           192:     irpSp = IoGetCurrentIrpStackLocation(Irp);
        !           193: 
        !           194:     //
        !           195:     // Case on the device control subfunction that is being performed by the
        !           196:     // requestor.
        !           197:     //
        !           198: 
        !           199:     switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
        !           200: 
        !           201:         //
        !           202:         // Connect a mouse class device driver to the port driver.
        !           203:         //
        !           204: 
        !           205:         case IOCTL_INTERNAL_MOUSE_CONNECT:
        !           206: 
        !           207:             SerMouPrint((
        !           208:                 2,
        !           209:                 "SERMOUSE-SerialMouseInternalDeviceControl: mouse connect\n"
        !           210:                 ));
        !           211: 
        !           212:             //
        !           213:             // Only allow one connection.
        !           214:             //
        !           215:             // FUTURE:  Consider allowing multiple connections, just for
        !           216:             // the sake of generality?
        !           217:             //
        !           218: 
        !           219:             if (deviceExtension->ConnectData.ClassService
        !           220:                 != NULL) {
        !           221: 
        !           222:                 SerMouPrint((
        !           223:                     2,
        !           224:                     "SERMOUSE-SerialMouseInternalDeviceControl: error - already connected\n"
        !           225:                     ));
        !           226: 
        !           227:                 status = STATUS_SHARING_VIOLATION;
        !           228:                 break;
        !           229: 
        !           230:             } else
        !           231:             if (irpSp->Parameters.DeviceIoControl.InputBufferLength <
        !           232:                     sizeof(CONNECT_DATA)) {
        !           233: 
        !           234:                 SerMouPrint((
        !           235:                     2,
        !           236:                     "SERMOUSE-SerialMouseInternalDeviceControl: error - invalid buffer length\n"
        !           237:                     ));
        !           238: 
        !           239:                 status = STATUS_INVALID_PARAMETER;
        !           240:                 break;
        !           241:             }
        !           242: 
        !           243:             //
        !           244:             // Copy the connection parameters to the device extension.
        !           245:             //
        !           246: 
        !           247:             deviceExtension->ConnectData =
        !           248:                 *((PCONNECT_DATA) (irpSp->Parameters.DeviceIoControl.Type3InputBuffer));
        !           249: 
        !           250:             //
        !           251:             // Reinitialize the port input data queue synchronously.
        !           252:             //
        !           253: 
        !           254:             KeSynchronizeExecution(
        !           255:                 deviceExtension->InterruptObject,
        !           256:                 (PKSYNCHRONIZE_ROUTINE) SerMouInitializeDataQueue,
        !           257:                 (PVOID) deviceExtension
        !           258:                 );
        !           259: 
        !           260:             //
        !           261:             // Set the completion status.
        !           262:             //
        !           263: 
        !           264:             status = STATUS_SUCCESS;
        !           265:             break;
        !           266: 
        !           267:         //
        !           268:         // Disconnect a mouse class device driver from the port driver.
        !           269:         //
        !           270:         // NOTE: Not implemented.
        !           271:         //
        !           272: 
        !           273:         case IOCTL_INTERNAL_MOUSE_DISCONNECT:
        !           274: 
        !           275:             SerMouPrint((
        !           276:                 2,
        !           277:                 "SERMOUSE-SerialMouseInternalDeviceControl: mouse disconnect\n"
        !           278:                 ));
        !           279: 
        !           280:             //
        !           281:             // Perform a mouse interrupt disable call.
        !           282:             //
        !           283: 
        !           284:             //
        !           285:             // Clear the connection parameters in the device extension.
        !           286:             // NOTE:  Must synchronize this with the mouse ISR.
        !           287:             //
        !           288:             //
        !           289:             //deviceExtension->ConnectData.ClassDeviceObject =
        !           290:             //    Null;
        !           291:             //deviceExtension->ConnectData.ClassService =
        !           292:             //    Null;
        !           293: 
        !           294:             //
        !           295:             // Set the completion status.
        !           296:             //
        !           297: 
        !           298:             status = STATUS_NOT_IMPLEMENTED;
        !           299:             break;
        !           300: 
        !           301:         //
        !           302:         // Enable mouse interrupts (mark the request pending and handle
        !           303:         // it in StartIo).
        !           304:         //
        !           305: 
        !           306:         case IOCTL_INTERNAL_MOUSE_ENABLE:
        !           307: 
        !           308:             SerMouPrint((
        !           309:                 2,
        !           310:                 "SERMOUSE-SerialMouseInternalDeviceControl: mouse enable\n"
        !           311:                 ));
        !           312: 
        !           313:             status = STATUS_PENDING;
        !           314:             break;
        !           315: 
        !           316:         //
        !           317:         // Disable mouse interrupts (mark the request pending and handle
        !           318:         // it in StartIo).
        !           319:         //
        !           320: 
        !           321:         case IOCTL_INTERNAL_MOUSE_DISABLE:
        !           322: 
        !           323:             SerMouPrint((
        !           324:                 2,
        !           325:                 "SERMOUSE-SerialMouseInternalDeviceControl: mouse disable\n"
        !           326:                 ));
        !           327: 
        !           328:             status = STATUS_PENDING;
        !           329:             break;
        !           330: 
        !           331:         //
        !           332:         // Query the mouse attributes.  First check for adequate buffer
        !           333:         // length.  Then, copy the mouse attributes from the device
        !           334:         // extension to the output buffer.
        !           335:         //
        !           336: 
        !           337:         case IOCTL_MOUSE_QUERY_ATTRIBUTES:
        !           338: 
        !           339:             SerMouPrint((
        !           340:                 2,
        !           341:                 "SERMOUSE-SerialMouseInternalDeviceControl: mouse query attributes\n"
        !           342:                 ));
        !           343: 
        !           344:             if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !           345:                 sizeof(MOUSE_ATTRIBUTES)) {
        !           346:                 status = STATUS_BUFFER_TOO_SMALL;
        !           347:             } else {
        !           348: 
        !           349:                 //
        !           350:                 // Copy the attributes from the DeviceExtension to the
        !           351:                 // buffer.
        !           352:                 //
        !           353: 
        !           354:                 *(PMOUSE_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer =
        !           355:                     deviceExtension->Configuration.MouseAttributes;
        !           356: 
        !           357:                 Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
        !           358:                 status = STATUS_SUCCESS;
        !           359:             }
        !           360: 
        !           361:             break;
        !           362: 
        !           363:         default:
        !           364: 
        !           365:             SerMouPrint((
        !           366:                 2,
        !           367:                 "SERMOUSE-SerialMouseInternalDeviceControl: INVALID REQUEST\n"
        !           368:                 ));
        !           369: 
        !           370:             status = STATUS_INVALID_DEVICE_REQUEST;
        !           371:             break;
        !           372:     }
        !           373: 
        !           374:     Irp->IoStatus.Status = status;
        !           375:     if (status == STATUS_PENDING) {
        !           376:         IoMarkIrpPending(Irp);
        !           377:         IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL);
        !           378:     } else {
        !           379:         IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !           380:     }
        !           381: 
        !           382:     SerMouPrint((2,"SERMOUSE-SerialMouseInternalDeviceControl: exit\n"));
        !           383: 
        !           384:     return(status);
        !           385: 
        !           386: }
        !           387: 
        !           388: BOOLEAN
        !           389: SerialMouseInterruptService(
        !           390:     IN PKINTERRUPT Interrupt,
        !           391:     IN PVOID Context
        !           392:     )
        !           393: 
        !           394: /*++
        !           395: 
        !           396: Routine Description:
        !           397: 
        !           398:     This is the interrupt service routine for the mouse device.
        !           399: 
        !           400: Arguments:
        !           401: 
        !           402:     Interrupt - A pointer to the interrupt object for this interrupt.
        !           403: 
        !           404:     Context - A pointer to the device object.
        !           405: 
        !           406: Return Value:
        !           407: 
        !           408:     Returns TRUE if the interrupt was expected (and therefore processed);
        !           409:     otherwise, FALSE is returned.
        !           410: 
        !           411: --*/
        !           412: 
        !           413: {
        !           414:     PDEVICE_EXTENSION deviceExtension;
        !           415:     PDEVICE_OBJECT deviceObject;
        !           416:     PMOUSE_INPUT_DATA currentInput;
        !           417:     PUCHAR port;
        !           418:     UCHAR value;
        !           419:     UCHAR lineState;
        !           420:     ULONG buttonsDelta;
        !           421: 
        !           422:     UNREFERENCED_PARAMETER(Interrupt);
        !           423: 
        !           424:     SerMouPrint((2, "SERMOUSE-SerialMouseInterruptService: enter\n"));
        !           425: 
        !           426:     //
        !           427:     // Get the device extension.
        !           428:     //
        !           429: 
        !           430:     deviceObject = (PDEVICE_OBJECT) Context;
        !           431:     deviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
        !           432: 
        !           433:     //
        !           434:     // Get the serial mouse port address.
        !           435:     //
        !           436: 
        !           437:     port = deviceExtension->Configuration.DeviceRegisters[0];
        !           438: 
        !           439:     //
        !           440:     // Verify that the interrupt really belongs to this driver.
        !           441:     //
        !           442: 
        !           443:     if ((READ_PORT_UCHAR((PUCHAR) (port + ACE_IIDR)) & ACE_IIP) == ACE_IIP) {
        !           444: 
        !           445:         //
        !           446:         // Not our interrupt.
        !           447:         //
        !           448: 
        !           449:         SerMouPrint((
        !           450:             2,
        !           451:             "SERMOUSE-SerialMouseInterruptService: not our interrupt\n"
        !           452:             ));
        !           453:         return(FALSE);
        !           454:     }
        !           455: 
        !           456:     //
        !           457:     // Get the line state byte. This value can be checked by the
        !           458:     // protocol handler for errors.
        !           459:     //
        !           460: 
        !           461:     lineState = READ_PORT_UCHAR((PUCHAR) (port + ACE_LSR));
        !           462:     SerMouPrint((
        !           463:         2,
        !           464:         "SERMOUSE-Line status: 0x%x\n", lineState
        !           465:         ));
        !           466: 
        !           467:     //
        !           468:     // Read the byte from the serial mouse port.  If the mouse has not
        !           469:     // been enabled, don't process the byte further.
        !           470:     //
        !           471: 
        !           472:     value = READ_PORT_UCHAR((PUCHAR) port + ACE_RBR);
        !           473: 
        !           474:     SerMouPrint((
        !           475:         2,
        !           476:         "SERMOUSE-SerialMouseInterruptService: byte 0x%x\n", value
        !           477:         ));
        !           478: 
        !           479:     if (deviceExtension->MouseEnableCount == 0) {
        !           480:         SerMouPrint((
        !           481:             2,
        !           482:             "SERMOUSE-SerialMouseInterruptService: not enabled\n"
        !           483:             ));
        !           484:         return(TRUE);
        !           485:     }
        !           486: 
        !           487:     //
        !           488:     // At this point, the protocol handler should already be set because
        !           489:     // the hardware is enabled.
        !           490:     //
        !           491: 
        !           492:     ASSERT(deviceExtension->ProtocolHandler);
        !           493: 
        !           494:     currentInput = &deviceExtension->CurrentInput;
        !           495: 
        !           496:     //
        !           497:     // Call the current protocol handler for this device
        !           498:     //
        !           499: 
        !           500:     if ((*deviceExtension->ProtocolHandler)(
        !           501:               currentInput,
        !           502:               &deviceExtension->HandlerData,
        !           503:               value,
        !           504:               lineState
        !           505:               )){
        !           506: 
        !           507:         //
        !           508:         // The report is complete, compute the button deltas and queue it.
        !           509:         //
        !           510: 
        !           511:         currentInput->UnitId = deviceExtension->UnitId;
        !           512:         currentInput->Buttons = 0;
        !           513: 
        !           514:         //
        !           515:         // Do we have a button state change?
        !           516:         //
        !           517: 
        !           518:         if (deviceExtension->HandlerData.PreviousButtons ^ currentInput->RawButtons) {
        !           519: 
        !           520: 
        !           521:             //
        !           522:             // The state of the buttons changed. Make some calculations...
        !           523:             //
        !           524: 
        !           525:             buttonsDelta = deviceExtension->HandlerData.PreviousButtons ^
        !           526:                                 currentInput->RawButtons;
        !           527: 
        !           528:             //
        !           529:             // Button 1.
        !           530:             //
        !           531: 
        !           532:             if (buttonsDelta & MOUSE_BUTTON_1) {
        !           533:                 if (currentInput->RawButtons & MOUSE_BUTTON_1) {
        !           534:                     currentInput->Buttons |= MOUSE_BUTTON_1_DOWN;
        !           535:                 }
        !           536:                 else {
        !           537:                     currentInput->Buttons |= MOUSE_BUTTON_1_UP;
        !           538:                 }
        !           539:             }
        !           540: 
        !           541:             //
        !           542:             // Button 2.
        !           543:             //
        !           544: 
        !           545:             if (buttonsDelta & MOUSE_BUTTON_2) {
        !           546:                 if (currentInput->RawButtons & MOUSE_BUTTON_2) {
        !           547:                     currentInput->Buttons |= MOUSE_BUTTON_2_DOWN;
        !           548:                 }
        !           549:                 else {
        !           550:                     currentInput->Buttons |= MOUSE_BUTTON_2_UP;
        !           551:                 }
        !           552:             }
        !           553: 
        !           554:             //
        !           555:             // Button 3.
        !           556:             //
        !           557: 
        !           558:             if (buttonsDelta & MOUSE_BUTTON_3) {
        !           559:                 if (currentInput->RawButtons & MOUSE_BUTTON_3) {
        !           560:                     currentInput->Buttons |= MOUSE_BUTTON_3_DOWN;
        !           561:                 }
        !           562:                 else {
        !           563:                     currentInput->Buttons |= MOUSE_BUTTON_3_UP;
        !           564:                 }
        !           565:             }
        !           566: 
        !           567:             deviceExtension->HandlerData.PreviousButtons = 
        !           568:                 currentInput->RawButtons;
        !           569: 
        !           570:         }
        !           571: 
        !           572:         SerMouPrint((1, "SERMOUSE-Buttons: %0lx\n", currentInput->Buttons));
        !           573: 
        !           574:         SerMouSendReport(deviceObject);
        !           575:     }
        !           576: 
        !           577:     SerMouPrint((2, "SERMOUSE-SerialMouseInterruptService: exit\n"));
        !           578: 
        !           579:     return TRUE;
        !           580: }
        !           581: 
        !           582: VOID
        !           583: SerialMouseIsrDpc(
        !           584:     IN PKDPC Dpc,
        !           585:     IN PDEVICE_OBJECT DeviceObject,
        !           586:     IN PIRP Irp,
        !           587:     IN PVOID Context
        !           588:     )
        !           589: 
        !           590: /*++
        !           591: 
        !           592: Routine Description:
        !           593: 
        !           594:     This routine runs at DISPATCH_LEVEL IRQL to finish processing
        !           595:     mouse interrupts.  It is queued in the mouse ISR.  The real
        !           596:     work is done via a callback to the connected mouse class driver.
        !           597: 
        !           598: Arguments:
        !           599: 
        !           600:     Dpc - Pointer to the DPC object.
        !           601: 
        !           602:     DeviceObject - Pointer to the device object.
        !           603: 
        !           604:     Irp - Pointer to the Irp.
        !           605: 
        !           606:     Context - Not used.
        !           607: 
        !           608: Return Value:
        !           609: 
        !           610:     None.
        !           611: 
        !           612: --*/
        !           613: 
        !           614: {
        !           615: 
        !           616:     PDEVICE_EXTENSION deviceExtension;
        !           617:     GET_DATA_POINTER_CONTEXT getPointerContext;
        !           618:     SET_DATA_POINTER_CONTEXT setPointerContext;
        !           619:     VARIABLE_OPERATION_CONTEXT operationContext;
        !           620:     PVOID classService;
        !           621:     PVOID classDeviceObject;
        !           622:     LONG interlockedResult;
        !           623:     BOOLEAN moreDpcProcessing;
        !           624:     ULONG dataNotConsumed = 0;
        !           625:     ULONG inputDataConsumed = 0;
        !           626:     LARGE_INTEGER deltaTime;
        !           627: 
        !           628:     UNREFERENCED_PARAMETER(Dpc);
        !           629:     UNREFERENCED_PARAMETER(Irp);
        !           630:     UNREFERENCED_PARAMETER(Context);
        !           631: 
        !           632:     SerMouPrint((2, "SERMOUSE-SerialMouseIsrDpc: enter\n"));
        !           633: 
        !           634:     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
        !           635: 
        !           636:     //
        !           637:     // Use DpcInterlockVariable to determine whether the DPC is running
        !           638:     // concurrently on another processor.  We only want one instantiation
        !           639:     // of the DPC to actually do any work.  DpcInterlockVariable is -1
        !           640:     // when no DPC is executing.  We increment it, and if the result is
        !           641:     // zero then the current instantiation is the only one executing, and it
        !           642:     // is okay to proceed.  Otherwise, we just return.
        !           643:     //
        !           644:     //
        !           645: 
        !           646:     operationContext.VariableAddress = 
        !           647:         &deviceExtension->DpcInterlockVariable;
        !           648:     operationContext.Operation = IncrementOperation;
        !           649:     operationContext.NewValue = &interlockedResult;
        !           650: 
        !           651:     KeSynchronizeExecution(
        !           652:             deviceExtension->InterruptObject,
        !           653:             (PKSYNCHRONIZE_ROUTINE) SerMouDpcVariableOperation,
        !           654:             (PVOID) &operationContext
        !           655:             );
        !           656: 
        !           657:     moreDpcProcessing = (interlockedResult == 0)? TRUE:FALSE;
        !           658: 
        !           659:     while (moreDpcProcessing) {
        !           660: 
        !           661:         dataNotConsumed = 0;
        !           662:         inputDataConsumed = 0;
        !           663: 
        !           664:         //
        !           665:         // Get the port InputData queue pointers synchronously.
        !           666:         //
        !           667: 
        !           668:         getPointerContext.DeviceExtension = deviceExtension;
        !           669:         setPointerContext.DeviceExtension = deviceExtension;
        !           670:         setPointerContext.InputCount = 0;
        !           671: 
        !           672:         KeSynchronizeExecution(
        !           673:             deviceExtension->InterruptObject,
        !           674:             (PKSYNCHRONIZE_ROUTINE) SerMouGetDataQueuePointer,
        !           675:             (PVOID) &getPointerContext
        !           676:             );
        !           677: 
        !           678:         if (getPointerContext.InputCount != 0) {
        !           679: 
        !           680:             //
        !           681:             // Call the connected class driver's callback ISR with the
        !           682:             // port InputData queue pointers.  If we have to wrap the queue,
        !           683:             // break the operation into two pieces, and call the class callback
        !           684:             // ISR once for each piece.
        !           685:             //
        !           686: 
        !           687:             classDeviceObject =
        !           688:                 deviceExtension->ConnectData.ClassDeviceObject;
        !           689:             classService =
        !           690:                 deviceExtension->ConnectData.ClassService;
        !           691:             ASSERT(classService != NULL);
        !           692: 
        !           693:             if (getPointerContext.DataOut >= getPointerContext.DataIn) {
        !           694: 
        !           695:                 //
        !           696:                 // We'll have to wrap the InputData circular buffer.  Call
        !           697:                 // the class callback ISR with the chunk of data starting at
        !           698:                 // DataOut and ending at the end of the queue.
        !           699:                 //
        !           700: 
        !           701:                 SerMouPrint((
        !           702:                     2,
        !           703:                     "SERMOUSE-SerialMouseIsrDpc: calling class callback\n"
        !           704:                     ));
        !           705:                 SerMouPrint((
        !           706:                     2,
        !           707:                     "SERMOUSE-SerialMouseIsrDpc: with Start 0x%x and End 0x%x\n",
        !           708:                     getPointerContext.DataOut,
        !           709:                     deviceExtension->DataEnd
        !           710:                     ));
        !           711: 
        !           712:                 (*(PSERVICE_CALLBACK_ROUTINE) classService)(
        !           713:                       classDeviceObject,
        !           714:                       getPointerContext.DataOut,
        !           715:                       deviceExtension->DataEnd,
        !           716:                       &inputDataConsumed
        !           717:                       );
        !           718: 
        !           719:                 dataNotConsumed = (((PUCHAR)
        !           720:                     deviceExtension->DataEnd -
        !           721:                     (PUCHAR) getPointerContext.DataOut)
        !           722:                     / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
        !           723: 
        !           724:                 SerMouPrint((
        !           725:                     2,
        !           726:                     "SERMOUSE-SerialMouseIsrDpc: (Wrap) Call callback consumed %d items, left %d\n",
        !           727:                     inputDataConsumed,
        !           728:                     dataNotConsumed
        !           729:                     ));
        !           730: 
        !           731:                 setPointerContext.InputCount += inputDataConsumed;
        !           732: 
        !           733:                 if (dataNotConsumed) {
        !           734:                     setPointerContext.DataOut =
        !           735:                         ((PUCHAR)getPointerContext.DataOut) +
        !           736:                         (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
        !           737:                 } else {
        !           738:                     setPointerContext.DataOut =
        !           739:                         deviceExtension->InputData;
        !           740:                     getPointerContext.DataOut = setPointerContext.DataOut;
        !           741:                 }
        !           742:             }
        !           743: 
        !           744:             //
        !           745:             // Call the class callback ISR with data remaining in the queue.
        !           746:             //
        !           747: 
        !           748:             if ((dataNotConsumed == 0) &&
        !           749:                 (inputDataConsumed < getPointerContext.InputCount)){
        !           750:                 SerMouPrint((
        !           751:                     2,
        !           752:                     "SERMOUSE-SerialMouseIsrDpc: calling class callback\n"
        !           753:                     ));
        !           754:                 SerMouPrint((
        !           755:                     2,
        !           756:                     "SERMOUSE-SerialMouseIsrDpc: with Start 0x%x and End 0x%x\n",
        !           757:                     getPointerContext.DataOut,
        !           758:                     getPointerContext.DataIn
        !           759:                     ));
        !           760: 
        !           761:                 (*(PSERVICE_CALLBACK_ROUTINE) classService)(
        !           762:                       classDeviceObject,
        !           763:                       getPointerContext.DataOut,
        !           764:                       getPointerContext.DataIn,
        !           765:                       &inputDataConsumed
        !           766:                       );
        !           767: 
        !           768:                 dataNotConsumed = (((PUCHAR) getPointerContext.DataIn -
        !           769:                       (PUCHAR) getPointerContext.DataOut)
        !           770:                       / sizeof(MOUSE_INPUT_DATA)) - inputDataConsumed;
        !           771: 
        !           772:                 SerMouPrint((
        !           773:                     2,
        !           774:                     "SERMOUSE-SerialMouseIsrDpc: Call callback consumed %d items, left %d\n",
        !           775:                     inputDataConsumed,
        !           776:                     dataNotConsumed
        !           777:                     ));
        !           778: 
        !           779:                 setPointerContext.DataOut =
        !           780:                     ((PUCHAR)getPointerContext.DataOut) +
        !           781:                     (inputDataConsumed * sizeof(MOUSE_INPUT_DATA));
        !           782:                 setPointerContext.InputCount += inputDataConsumed;
        !           783: 
        !           784:             }
        !           785: 
        !           786:             //
        !           787:             // Update the port InputData queue DataOut pointer and InputCount
        !           788:             // synchronously.
        !           789:             //
        !           790: 
        !           791:             KeSynchronizeExecution(
        !           792:                 deviceExtension->InterruptObject,
        !           793:                 (PKSYNCHRONIZE_ROUTINE) SerMouSetDataQueuePointer,
        !           794:                 (PVOID) &setPointerContext
        !           795:                 );
        !           796: 
        !           797:         }
        !           798: 
        !           799:         if (dataNotConsumed) {
        !           800: 
        !           801:             //
        !           802:             // The class driver was unable to consume all the data.
        !           803:             // Reset the interlocked variable to -1.  We do not want
        !           804:             // to attempt to move more data to the class driver at this
        !           805:             // point, because it is already overloaded.  Need to wait a
        !           806:             // while to give the Raw Input Thread a chance to read some
        !           807:             // of the data out of the class driver's queue.  We accomplish
        !           808:             // this "wait" via a timer.
        !           809:             //
        !           810: 
        !           811:             SerMouPrint((2, "SERMOUSE-SerialMouseIsrDpc: set timer in DPC\n"));
        !           812: 
        !           813:             operationContext.Operation = WriteOperation;
        !           814:             interlockedResult = -1;
        !           815:             operationContext.NewValue = &interlockedResult;
        !           816:         
        !           817:             KeSynchronizeExecution(
        !           818:                     deviceExtension->InterruptObject,
        !           819:                     (PKSYNCHRONIZE_ROUTINE) SerMouDpcVariableOperation,
        !           820:                     (PVOID) &operationContext
        !           821:                     );
        !           822: 
        !           823:             deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
        !           824:             deltaTime.HighPart = -1;
        !           825: 
        !           826:             (VOID) KeSetTimer(
        !           827:                        &deviceExtension->DataConsumptionTimer,
        !           828:                        deltaTime,
        !           829:                        &deviceExtension->IsrDpcRetry
        !           830:                        );
        !           831: 
        !           832:             moreDpcProcessing = FALSE;
        !           833: 
        !           834:         } else {
        !           835: 
        !           836:             //
        !           837:             // Decrement DpcInterlockVariable.  If the result goes negative,
        !           838:             // then we're all finished processing the DPC.  Otherwise, either
        !           839:             // the ISR incremented DpcInterlockVariable because it has more
        !           840:             // work for the ISR DPC to do, or a concurrent DPC executed on 
        !           841:             // some processor while the current DPC was running (the 
        !           842:             // concurrent DPC wouldn't have done any work).  Make sure that 
        !           843:             // the current DPC handles any extra work that is ready to be
        !           844:             // done.
        !           845:             //
        !           846: 
        !           847:             operationContext.Operation = DecrementOperation;
        !           848:             operationContext.NewValue = &interlockedResult;
        !           849:         
        !           850:             KeSynchronizeExecution(
        !           851:                     deviceExtension->InterruptObject,
        !           852:                     (PKSYNCHRONIZE_ROUTINE) SerMouDpcVariableOperation,
        !           853:                     (PVOID) &operationContext
        !           854:                     );
        !           855: 
        !           856:             if (interlockedResult != -1) {
        !           857: 
        !           858:                 //
        !           859:                 // The interlocked variable is still greater than or equal to
        !           860:                 // zero. Reset it to zero, so that we execute the loop one
        !           861:                 // more time (assuming no more DPCs execute and bump the
        !           862:                 // variable up again).
        !           863:                 //
        !           864: 
        !           865:                 operationContext.Operation = WriteOperation;
        !           866:                 interlockedResult = 0;
        !           867:                 operationContext.NewValue = &interlockedResult;
        !           868:         
        !           869:                 KeSynchronizeExecution(
        !           870:                     deviceExtension->InterruptObject,
        !           871:                     (PKSYNCHRONIZE_ROUTINE) SerMouDpcVariableOperation,
        !           872:                     (PVOID) &operationContext
        !           873:                     );
        !           874: 
        !           875:                 SerMouPrint((2, "SERMOUSE-SerialMouseIsrDpc: loop in DPC\n"));
        !           876:             } else {
        !           877:                 moreDpcProcessing = FALSE;
        !           878:             }
        !           879:         }
        !           880:     }
        !           881: 
        !           882:     SerMouPrint((2, "SERMOUSE-SerialMouseIsrDpc: exit\n"));
        !           883: 
        !           884: }
        !           885: 
        !           886: NTSTATUS
        !           887: SerialMouseOpenClose(
        !           888:     IN PDEVICE_OBJECT DeviceObject,
        !           889:     IN PIRP Irp
        !           890:     )
        !           891: 
        !           892: /*++
        !           893: 
        !           894: Routine Description:
        !           895: 
        !           896:     This is the dispatch routine for create/open and close requests.
        !           897:     These requests complete successfully.
        !           898: 
        !           899: Arguments:
        !           900: 
        !           901:     DeviceObject - Pointer to the device object.
        !           902: 
        !           903:     Irp - Pointer to the request packet.
        !           904: 
        !           905: Return Value:
        !           906: 
        !           907:     Status is returned.
        !           908: 
        !           909: --*/
        !           910: 
        !           911: {
        !           912: 
        !           913:     UNREFERENCED_PARAMETER(DeviceObject);
        !           914: 
        !           915:     SerMouPrint((3,"SERMOUSE-SerialMouseOpenClose: enter\n"));
        !           916: 
        !           917:     //
        !           918:     // Complete the request with successful status.
        !           919:     //
        !           920: 
        !           921:     Irp->IoStatus.Status = STATUS_SUCCESS;
        !           922:     Irp->IoStatus.Information = 0;
        !           923:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
        !           924: 
        !           925:     SerMouPrint((3,"SERMOUSE-SerialMouseOpenClose: exit\n"));
        !           926: 
        !           927:     return(STATUS_SUCCESS);
        !           928: 
        !           929: } // end SerialMouseOpenClose
        !           930: 
        !           931: VOID
        !           932: SerialMouseStartIo(
        !           933:     IN PDEVICE_OBJECT DeviceObject,
        !           934:     IN PIRP Irp
        !           935:     )
        !           936: 
        !           937: /*++
        !           938: 
        !           939: Routine Description:
        !           940: 
        !           941:     This routine starts an I/O operation for the device.
        !           942: 
        !           943: Arguments:
        !           944: 
        !           945:     DeviceObject - Pointer to the device object.
        !           946: 
        !           947:     Irp - Pointer to the request packet.
        !           948: 
        !           949: Return Value:
        !           950: 
        !           951:     None.
        !           952: 
        !           953: --*/
        !           954: 
        !           955: {
        !           956:     PDEVICE_EXTENSION deviceExtension;
        !           957:     PIO_STACK_LOCATION irpSp;
        !           958: 
        !           959:     SerMouPrint((2, "SERMOUSE-SerialMouseStartIo: enter\n"));
        !           960: 
        !           961:     deviceExtension = DeviceObject->DeviceExtension;
        !           962: 
        !           963:     //
        !           964:     // Bump the error log sequence number.
        !           965:     //
        !           966: 
        !           967:     deviceExtension->SequenceNumber += 1;
        !           968: 
        !           969:     //
        !           970:     // Get a pointer to the current parameters for this request.  The
        !           971:     // information is contained in the current stack location.
        !           972:     //
        !           973: 
        !           974:     irpSp = IoGetCurrentIrpStackLocation(Irp);
        !           975: 
        !           976:     //
        !           977:     // We know we got here with an internal device control request.  Switch
        !           978:     // on IoControlCode.
        !           979:     //
        !           980: 
        !           981:     switch(irpSp->Parameters.DeviceIoControl.IoControlCode) {
        !           982: 
        !           983:         //
        !           984:         // Enable mouse interrupts, by calling SerMouEnableInterrupts
        !           985:         // synchronously.
        !           986:         //
        !           987: 
        !           988:         case IOCTL_INTERNAL_MOUSE_ENABLE:
        !           989: 
        !           990:             KeSynchronizeExecution(
        !           991:                 deviceExtension->InterruptObject,
        !           992:                 (PKSYNCHRONIZE_ROUTINE) SerMouEnableInterrupts,
        !           993:                 (PVOID) deviceExtension
        !           994:                 );
        !           995: 
        !           996:             SerMouPrint((
        !           997:                 2,
        !           998:                 "SERMOUSE-SerialMouseStartIo: mouse enable (count %d)\n",
        !           999:                 deviceExtension->MouseEnableCount
        !          1000:                 ));
        !          1001: 
        !          1002:             Irp->IoStatus.Status = STATUS_SUCCESS;
        !          1003: 
        !          1004:             //
        !          1005:             // Complete the request.
        !          1006:             //
        !          1007: 
        !          1008:             IoStartNextPacket(DeviceObject, FALSE);
        !          1009:             IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
        !          1010: 
        !          1011:             break;
        !          1012: 
        !          1013:         //
        !          1014:         // Disable mouse interrupts, by calling SerMouDisableInterrupts
        !          1015:         // synchronously.
        !          1016:         //
        !          1017: 
        !          1018:         case IOCTL_INTERNAL_MOUSE_DISABLE:
        !          1019: 
        !          1020:             SerMouPrint((2, "SERMOUSE-SerialMouseStartIo: mouse disable"));
        !          1021: 
        !          1022:             if (deviceExtension->MouseEnableCount == 0) {
        !          1023: 
        !          1024:                 //
        !          1025:                 // Mouse already disabled.
        !          1026:                 //
        !          1027: 
        !          1028:                 SerMouPrint((2, " - error\n"));
        !          1029: 
        !          1030:                 Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
        !          1031: 
        !          1032:             } else {
        !          1033: 
        !          1034:                 //
        !          1035:                 // Disable mouse by calling SerMouDisableInterrupts.
        !          1036:                 //
        !          1037: 
        !          1038:                 KeSynchronizeExecution(
        !          1039:                     deviceExtension->InterruptObject,
        !          1040:                     (PKSYNCHRONIZE_ROUTINE) SerMouDisableInterrupts,
        !          1041:                     (PVOID) deviceExtension
        !          1042:                     );
        !          1043: 
        !          1044:                 SerMouPrint((
        !          1045:                     2,
        !          1046:                     " (count %d)\n",
        !          1047:                     deviceExtension->MouseEnableCount
        !          1048:                     ));
        !          1049: 
        !          1050:                 Irp->IoStatus.Status = STATUS_SUCCESS;
        !          1051:             }
        !          1052: 
        !          1053:             //
        !          1054:             // Complete the request.
        !          1055:             //
        !          1056: 
        !          1057:             IoStartNextPacket(DeviceObject, FALSE);
        !          1058:             IoCompleteRequest(Irp, IO_MOUSE_INCREMENT);
        !          1059: 
        !          1060:             break;
        !          1061: 
        !          1062:         default:
        !          1063: 
        !          1064:             SerMouPrint((2, "SERMOUSE-SerialMouseStartIo: INVALID REQUEST\n"));
        !          1065: 
        !          1066:             //
        !          1067:             // Log an internal error.  Note that we're calling the
        !          1068:             // error log DPC routine directly, rather than duplicating
        !          1069:             // code.
        !          1070:             //
        !          1071: 
        !          1072:             SerialMouseErrorLogDpc(
        !          1073:                 (PKDPC) NULL,
        !          1074:                 DeviceObject,
        !          1075:                 Irp,
        !          1076:                 (PVOID) (ULONG) SERMOUSE_INVALID_STARTIO_REQUEST
        !          1077:                 );
        !          1078: 
        !          1079: 
        !          1080:             ASSERT(FALSE);
        !          1081:             break;
        !          1082:     }
        !          1083: 
        !          1084:     SerMouPrint((2, "SERMOUSE-SerialMouseStartIo: exit\n"));
        !          1085: 
        !          1086:     return;
        !          1087: }
        !          1088: 
        !          1089: VOID
        !          1090: SerMouDpcVariableOperation(
        !          1091:     IN  PVOID Context
        !          1092:     )
        !          1093: 
        !          1094: /*++
        !          1095: 
        !          1096: Routine Description:
        !          1097: 
        !          1098:     This routine is called synchronously by the ISR DPC to perform an 
        !          1099:     operation on the InterlockedDpcVariable.  The operations that can be 
        !          1100:     performed include increment, decrement, write, and read.  The ISR 
        !          1101:     itself reads and writes the InterlockedDpcVariable without calling this 
        !          1102:     routine.  
        !          1103: 
        !          1104: Arguments:
        !          1105: 
        !          1106:     Context - Pointer to a structure containing the address of the variable
        !          1107:         to be operated on, the operation to perform, and the address at
        !          1108:         which to copy the resulting value of the variable (the latter is also
        !          1109:         used to pass in the value to write to the variable, on a write
        !          1110:         operation).
        !          1111: 
        !          1112: Return Value:
        !          1113: 
        !          1114:     None.
        !          1115: 
        !          1116: --*/
        !          1117: 
        !          1118: {
        !          1119:     PVARIABLE_OPERATION_CONTEXT operationContext = Context;
        !          1120: 
        !          1121:     SerMouPrint((3,"SERMOUSE-SerMouDpcVariableOperation: enter\n"));
        !          1122:     SerMouPrint((
        !          1123:         3,
        !          1124:         "\tPerforming %s at 0x%x (current value 0x%x)\n",
        !          1125:         (operationContext->Operation == IncrementOperation)? "increment":
        !          1126:         (operationContext->Operation == DecrementOperation)? "decrement":
        !          1127:         (operationContext->Operation == WriteOperation)?     "write":
        !          1128:         (operationContext->Operation == ReadOperation)?      "read":"",
        !          1129:         operationContext->VariableAddress,
        !          1130:         *(operationContext->VariableAddress)
        !          1131:         ));
        !          1132: 
        !          1133:     //
        !          1134:     // Perform the specified operation at the specified address.
        !          1135:     //
        !          1136: 
        !          1137:     switch(operationContext->Operation) {
        !          1138:         case IncrementOperation:
        !          1139:             *(operationContext->VariableAddress) += 1;
        !          1140:             break;
        !          1141:         case DecrementOperation:
        !          1142:             *(operationContext->VariableAddress) -= 1;
        !          1143:             break;
        !          1144:         case ReadOperation:
        !          1145:             break;
        !          1146:         case WriteOperation:
        !          1147:             SerMouPrint((
        !          1148:                 3,
        !          1149:                 "\tWriting 0x%x\n",
        !          1150:                 *(operationContext->NewValue)
        !          1151:                 ));
        !          1152:             *(operationContext->VariableAddress) = 
        !          1153:                 *(operationContext->NewValue);
        !          1154:             break;
        !          1155:         default:
        !          1156:             ASSERT(FALSE);
        !          1157:             break;
        !          1158:     }
        !          1159: 
        !          1160:     *(operationContext->NewValue) = *(operationContext->VariableAddress);
        !          1161: 
        !          1162:     SerMouPrint((
        !          1163:         3,
        !          1164:         "SERMOUSE-SerMouDpcVariableOperation: exit with value 0x%x\n",
        !          1165:         *(operationContext->NewValue)
        !          1166:         ));
        !          1167: }
        !          1168: 
        !          1169: VOID
        !          1170: SerMouGetDataQueuePointer(
        !          1171:     IN  PVOID Context
        !          1172:     )
        !          1173: 
        !          1174: /*++
        !          1175: 
        !          1176: Routine Description:
        !          1177: 
        !          1178:     This routine is called synchronously to get the current DataIn and DataOut
        !          1179:     pointers for the port InputData queue.
        !          1180: 
        !          1181: Arguments:
        !          1182: 
        !          1183:     Context - Pointer to a structure containing the device extension,
        !          1184:         address at which to store the current DataIn pointer, and the
        !          1185:         address at which to store the current DataOut pointer.
        !          1186: 
        !          1187: Return Value:
        !          1188: 
        !          1189:     None.
        !          1190: 
        !          1191: --*/
        !          1192: 
        !          1193: {
        !          1194:     PDEVICE_EXTENSION deviceExtension;
        !          1195: 
        !          1196:     SerMouPrint((3,"SERMOUSE-SerMouGetDataQueuePointer: enter\n"));
        !          1197: 
        !          1198:     //
        !          1199:     // Get address of device extension.
        !          1200:     //
        !          1201: 
        !          1202:     deviceExtension = (PDEVICE_EXTENSION)
        !          1203:                       ((PGET_DATA_POINTER_CONTEXT) Context)->DeviceExtension;
        !          1204: 
        !          1205:     //
        !          1206:     // Get the DataIn and DataOut pointers.
        !          1207:     //
        !          1208: 
        !          1209:     SerMouPrint((
        !          1210:         3,
        !          1211:         "SERMOUSE-SerMouGetDataQueuePointer: DataIn 0x%x, DataOut 0x%x\n",
        !          1212:         deviceExtension->DataIn,
        !          1213:         deviceExtension->DataOut
        !          1214:         ));
        !          1215:     ((PGET_DATA_POINTER_CONTEXT) Context)->DataIn = deviceExtension->DataIn;
        !          1216:     ((PGET_DATA_POINTER_CONTEXT) Context)->DataOut = deviceExtension->DataOut;
        !          1217:     ((PGET_DATA_POINTER_CONTEXT) Context)->InputCount =
        !          1218:         deviceExtension->InputCount;
        !          1219: 
        !          1220:     SerMouPrint((3,"SERMOUSE-SerMouGetDataQueuePointer: exit\n"));
        !          1221: }
        !          1222: 
        !          1223: VOID
        !          1224: SerMouInitializeDataQueue (
        !          1225:     IN PVOID Context
        !          1226:     )
        !          1227: 
        !          1228: /*++
        !          1229: 
        !          1230: Routine Description:
        !          1231: 
        !          1232:     This routine initializes the input data queue.  It is called
        !          1233:     via KeSynchronization, except when called from the initialization routine.
        !          1234: 
        !          1235: Arguments:
        !          1236: 
        !          1237:     Context - Pointer to the device extension.
        !          1238: 
        !          1239: Return Value:
        !          1240: 
        !          1241:     None.
        !          1242: 
        !          1243: --*/
        !          1244: 
        !          1245: {
        !          1246: 
        !          1247:     PDEVICE_EXTENSION deviceExtension;
        !          1248: 
        !          1249:     SerMouPrint((3,"SERMOUSE-SerMouInitializeDataQueue: enter\n"));
        !          1250: 
        !          1251:     //
        !          1252:     // Get address of device extension.
        !          1253:     //
        !          1254: 
        !          1255:     deviceExtension = (PDEVICE_EXTENSION) Context;
        !          1256: 
        !          1257:     //
        !          1258:     // Initialize the input data queue.
        !          1259:     //
        !          1260: 
        !          1261:     deviceExtension->InputCount = 0;
        !          1262:     deviceExtension->DataIn = deviceExtension->InputData;
        !          1263:     deviceExtension->DataOut = deviceExtension->InputData;
        !          1264: 
        !          1265:     deviceExtension->OkayToLogOverflow = TRUE;
        !          1266: 
        !          1267:     SerMouPrint((3,"SERMOUSE-SerMouInitializeDataQueue: exit\n"));
        !          1268: 
        !          1269: } // end SerMouInitializeDataQueue
        !          1270: 
        !          1271: VOID
        !          1272: SerMouSendReport(
        !          1273:     IN PDEVICE_OBJECT DeviceObject
        !          1274:     )
        !          1275: /*++
        !          1276: 
        !          1277: Routine Description:
        !          1278: 
        !          1279:     Place a completed report in the queue for subsequent processing by a DPC.
        !          1280: 
        !          1281: Arguments:
        !          1282: 
        !          1283:     Device Object - Pointer to the device object.
        !          1284: 
        !          1285: Return Value:
        !          1286: 
        !          1287:     None.
        !          1288: 
        !          1289: --*/
        !          1290: 
        !          1291: {
        !          1292:     PDEVICE_EXTENSION deviceExtension;
        !          1293: 
        !          1294:     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
        !          1295: 
        !          1296:     if (!SerMouWriteDataToQueue(
        !          1297:                 deviceExtension,
        !          1298:                 &deviceExtension->CurrentInput
        !          1299:                 )) {
        !          1300: 
        !          1301:         //
        !          1302:         // The mouse input data queue is full.  Just drop the
        !          1303:         // latest input on the floor.
        !          1304:         //
        !          1305:         // Queue a DPC to log an overrun error.
        !          1306:         //
        !          1307: 
        !          1308:         SerMouPrint((
        !          1309:             1,
        !          1310:             "SERMOUSE-SerMouSendReport: queue overflow\n"
        !          1311:             ));
        !          1312: 
        !          1313:         if (deviceExtension->OkayToLogOverflow) {
        !          1314:             KeInsertQueueDpc(
        !          1315:                 &deviceExtension->ErrorLogDpc,
        !          1316:                 (PIRP) NULL,
        !          1317:                 (PVOID) (ULONG) SERMOUSE_MOU_BUFFER_OVERFLOW
        !          1318:                 );
        !          1319:             deviceExtension->OkayToLogOverflow = FALSE;
        !          1320:         }
        !          1321: 
        !          1322:     } else if (deviceExtension->DpcInterlockVariable >= 0) {
        !          1323: 
        !          1324:         //
        !          1325:         // The ISR DPC is already executing.  Tell the ISR DPC it has
        !          1326:         // more work to do by incrementing the DpcInterlockVariable.
        !          1327:         //
        !          1328: 
        !          1329:         deviceExtension->DpcInterlockVariable += 1;
        !          1330: 
        !          1331:     } else {
        !          1332: 
        !          1333:         //
        !          1334:         // Queue the ISR DPC.
        !          1335:         //
        !          1336: 
        !          1337:         KeInsertQueueDpc(
        !          1338:             &deviceExtension->IsrDpc,
        !          1339:             DeviceObject->CurrentIrp,
        !          1340:             NULL
        !          1341:             );
        !          1342: 
        !          1343:     }
        !          1344: 
        !          1345:     return;
        !          1346: }
        !          1347: 
        !          1348: VOID
        !          1349: SerMouSetDataQueuePointer(
        !          1350:     IN  PVOID Context
        !          1351:     )
        !          1352: 
        !          1353: /*++
        !          1354: 
        !          1355: Routine Description:
        !          1356: 
        !          1357:     This routine is called synchronously to set the DataOut pointer
        !          1358:     and InputCount for the port InputData queue.
        !          1359: 
        !          1360: Arguments:
        !          1361: 
        !          1362:     Context - Pointer to a structure containing the device extension
        !          1363:         and the new DataOut value for the port InputData queue.
        !          1364: 
        !          1365: Return Value:
        !          1366: 
        !          1367:     None.
        !          1368: 
        !          1369: --*/
        !          1370: 
        !          1371: {
        !          1372:     PDEVICE_EXTENSION deviceExtension;
        !          1373: 
        !          1374:     SerMouPrint((3,"SERMOUSE-SerMouSetDataQueuePointer: enter\n"));
        !          1375: 
        !          1376:     //
        !          1377:     // Get address of device extension.
        !          1378:     //
        !          1379: 
        !          1380:     deviceExtension = (PDEVICE_EXTENSION)
        !          1381:                       ((PSET_DATA_POINTER_CONTEXT) Context)->DeviceExtension;
        !          1382: 
        !          1383:     //
        !          1384:     // Set the DataOut pointer.
        !          1385:     //
        !          1386: 
        !          1387:     SerMouPrint((
        !          1388:         3,
        !          1389:         "SERMOUSE-SerMouSetDataQueuePointer: old mouse DataOut 0x%x, InputCount %d\n",
        !          1390:         deviceExtension->DataOut,
        !          1391:         deviceExtension->InputCount
        !          1392:         ));
        !          1393:     deviceExtension->DataOut = ((PSET_DATA_POINTER_CONTEXT) Context)->DataOut;
        !          1394:     deviceExtension->InputCount -=
        !          1395:         ((PSET_DATA_POINTER_CONTEXT) Context)->InputCount;
        !          1396: 
        !          1397:     if (deviceExtension->InputCount == 0) {
        !          1398: 
        !          1399:         //
        !          1400:         // Reset the flag that determines whether it is time to log
        !          1401:         // queue overflow errors.  We don't want to log errors too often.
        !          1402:         // Instead, log an error on the first overflow that occurs after
        !          1403:         // the ring buffer has been emptied, and then stop logging errors
        !          1404:         // until it gets cleared out and overflows again.
        !          1405:         //
        !          1406: 
        !          1407:         SerMouPrint((
        !          1408:             1,
        !          1409:             "SERMOUSE-SerMouSetDataQueuePointer: Okay to log overflow\n"
        !          1410:             ));
        !          1411:         deviceExtension->OkayToLogOverflow = TRUE;
        !          1412:     }
        !          1413: 
        !          1414:     SerMouPrint((
        !          1415:         3,
        !          1416:         "SERMOUSE-SerMouSetDataQueuePointer: new mouse DataOut 0x%x, InputCount %d\n",
        !          1417:         deviceExtension->DataOut,
        !          1418:         deviceExtension->InputCount
        !          1419:         ));
        !          1420: 
        !          1421:     SerMouPrint((3,"SERMOUSE-SerMouSetDataQueuePointer: exit\n"));
        !          1422: }
        !          1423: 
        !          1424: BOOLEAN
        !          1425: SerMouWriteDataToQueue(
        !          1426:     PDEVICE_EXTENSION DeviceExtension,
        !          1427:     IN PMOUSE_INPUT_DATA InputData
        !          1428:     )
        !          1429: 
        !          1430: /*++
        !          1431: 
        !          1432: Routine Description:
        !          1433: 
        !          1434:     This routine adds input data from the mouse to the InputData queue.
        !          1435: 
        !          1436: Arguments:
        !          1437: 
        !          1438:     DeviceExtension - Pointer to the device extension.
        !          1439: 
        !          1440:     InputData - Pointer to the data to add to the InputData queue.
        !          1441: 
        !          1442: Return Value:
        !          1443: 
        !          1444:     Returns TRUE if the data was added, otherwise FALSE.
        !          1445: 
        !          1446: --*/
        !          1447: 
        !          1448: {
        !          1449: 
        !          1450:     SerMouPrint((2,"SERMOUSE-SerMouWriteDataToQueue: enter\n"));
        !          1451:     SerMouPrint((
        !          1452:         3,
        !          1453:         "SERMOUSE-SerMouWriteDataToQueue: DataIn 0x%x, DataOut 0x%x\n",
        !          1454:         DeviceExtension->DataIn,
        !          1455:         DeviceExtension->DataOut
        !          1456:         ));
        !          1457:     SerMouPrint((
        !          1458:         3,
        !          1459:         "SERMOUSE-SerMouWriteDataToQueue: InputCount %d\n",
        !          1460:         DeviceExtension->InputCount
        !          1461:         ));
        !          1462: 
        !          1463:     //
        !          1464:     // Check for full input data queue.
        !          1465:     //
        !          1466: 
        !          1467:     if ((DeviceExtension->DataIn == DeviceExtension->DataOut) &&
        !          1468:         (DeviceExtension->InputCount != 0)) {
        !          1469: 
        !          1470:         //
        !          1471:         // The input data queue is full.  Intentionally ignore
        !          1472:         // the new data.
        !          1473:         //
        !          1474: 
        !          1475:         SerMouPrint((1,"SERMOUSE-SerMouWriteDataToQueue: OVERFLOW\n"));
        !          1476:         return(FALSE);
        !          1477: 
        !          1478:     } else {
        !          1479:         *(DeviceExtension->DataIn) = *InputData;
        !          1480:         DeviceExtension->InputCount += 1;
        !          1481:         DeviceExtension->DataIn++;
        !          1482:         SerMouPrint((
        !          1483:             2,
        !          1484:             "SERMOUSE-SerMouWriteDataToQueue: new InputCount %d\n",
        !          1485:             DeviceExtension->InputCount
        !          1486:             ));
        !          1487:         if (DeviceExtension->DataIn ==
        !          1488:             DeviceExtension->DataEnd) {
        !          1489:             SerMouPrint((2,"SERMOUSE-SerMouWriteDataToQueue: wrap buffer\n"));
        !          1490:             DeviceExtension->DataIn = DeviceExtension->InputData;
        !          1491:         }
        !          1492:     }
        !          1493: 
        !          1494:     SerMouPrint((2,"SERMOUSE-SerMouWriteDataToQueue: exit\n"));
        !          1495: 
        !          1496:     return(TRUE);
        !          1497: }

unix.superglobalmegacorp.com

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