Annotation of ntddk/src/input/inport/i386/inpcmn.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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