Annotation of ntddk/src/input/sermouse/sermcmn.c, revision 1.1.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.