Annotation of ntddk/src/input/i8042prt/kbdcmn.c, revision 1.1

1.1     ! root        1: 
        !             2: /*++
        !             3: 
        !             4: Copyright (c) 1990, 1991, 1992, 1993  Microsoft Corporation
        !             5: 
        !             6: Module Name:
        !             7: 
        !             8:     kbdcmn.c
        !             9: 
        !            10: Abstract:
        !            11: 
        !            12:     The common portions of the Intel i8042 port driver which 
        !            13:     apply to the keyboard device.  
        !            14: 
        !            15: Environment:
        !            16: 
        !            17:     Kernel mode only.
        !            18: 
        !            19: Notes:
        !            20: 
        !            21:     NOTES:  (Future/outstanding issues)
        !            22: 
        !            23:     - Powerfail not implemented.
        !            24: 
        !            25:     - Consolidate duplicate code, where possible and appropriate.
        !            26: 
        !            27: Revision History:
        !            28: 
        !            29: --*/
        !            30: 
        !            31: #include "stdarg.h"
        !            32: #include "stdio.h"
        !            33: #include "string.h"
        !            34: #include "ntddk.h"
        !            35: #include "i8042prt.h"
        !            36: 
        !            37: 
        !            38: VOID
        !            39: I8042KeyboardIsrDpc(
        !            40:     IN PKDPC Dpc,
        !            41:     IN PDEVICE_OBJECT DeviceObject,
        !            42:     IN PIRP Irp,
        !            43:     IN PVOID Context
        !            44:     )
        !            45: 
        !            46: /*++
        !            47: 
        !            48: Routine Description:
        !            49: 
        !            50:     This routine runs at DISPATCH_LEVEL IRQL to finish processing
        !            51:     keyboard interrupts.  It is queued in the keyboard ISR.  The real
        !            52:     work is done via a callback to the connected keyboard class driver.
        !            53: 
        !            54: Arguments:
        !            55: 
        !            56:     Dpc - Pointer to the DPC object.
        !            57: 
        !            58:     DeviceObject - Pointer to the device object.
        !            59: 
        !            60:     Irp - Pointer to the Irp.
        !            61: 
        !            62:     Context - Not used.
        !            63: 
        !            64: Return Value:
        !            65: 
        !            66:     None.
        !            67: 
        !            68: --*/
        !            69: 
        !            70: {
        !            71: 
        !            72:     PDEVICE_EXTENSION deviceExtension;
        !            73:     GET_DATA_POINTER_CONTEXT getPointerContext;
        !            74:     SET_DATA_POINTER_CONTEXT setPointerContext;
        !            75:     VARIABLE_OPERATION_CONTEXT operationContext;
        !            76:     PVOID classService;
        !            77:     PVOID classDeviceObject;
        !            78:     LONG interlockedResult;
        !            79:     BOOLEAN moreDpcProcessing;
        !            80:     ULONG dataNotConsumed = 0;
        !            81:     ULONG inputDataConsumed = 0; 
        !            82:     LARGE_INTEGER deltaTime;
        !            83: 
        !            84:     UNREFERENCED_PARAMETER(Dpc);
        !            85:     UNREFERENCED_PARAMETER(Irp);
        !            86:     UNREFERENCED_PARAMETER(Context);
        !            87: 
        !            88:     I8xPrint((2, "I8042PRT-I8042KeyboardIsrDpc: enter\n"));
        !            89: 
        !            90:     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
        !            91: 
        !            92:     //
        !            93:     // Use DpcInterlockKeyboard to determine whether the DPC is running
        !            94:     // concurrently on another processor.  We only want one instantiation
        !            95:     // of the DPC to actually do any work.  DpcInterlockKeyboard is -1
        !            96:     // when no DPC is executing.  We increment it, and if the result is
        !            97:     // zero then the current instantiation is the only one executing, and it
        !            98:     // is okay to proceed.  Otherwise, we just return.
        !            99:     //
        !           100:     //
        !           101: 
        !           102:     operationContext.VariableAddress = 
        !           103:         &deviceExtension->DpcInterlockKeyboard;
        !           104:     operationContext.Operation = IncrementOperation;
        !           105:     operationContext.NewValue = &interlockedResult;
        !           106: 
        !           107:     KeSynchronizeExecution(
        !           108:             deviceExtension->KeyboardInterruptObject,
        !           109:             (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
        !           110:             (PVOID) &operationContext
        !           111:             );
        !           112: 
        !           113:     moreDpcProcessing = (interlockedResult == 0)? TRUE:FALSE;
        !           114: 
        !           115:     while (moreDpcProcessing) {
        !           116: 
        !           117:         dataNotConsumed = 0;
        !           118:         inputDataConsumed = 0;
        !           119: 
        !           120:         //
        !           121:         // Get the port InputData queue pointers synchronously.
        !           122:         //
        !           123:     
        !           124:         getPointerContext.DeviceExtension = deviceExtension;
        !           125:         setPointerContext.DeviceExtension = deviceExtension;
        !           126:         getPointerContext.DeviceType = (CCHAR) KeyboardDeviceType;
        !           127:         setPointerContext.DeviceType = (CCHAR) KeyboardDeviceType;
        !           128:         setPointerContext.InputCount = 0;
        !           129:     
        !           130:         KeSynchronizeExecution(
        !           131:             deviceExtension->KeyboardInterruptObject,
        !           132:             (PKSYNCHRONIZE_ROUTINE) I8xGetDataQueuePointer,
        !           133:             (PVOID) &getPointerContext
        !           134:             );
        !           135:     
        !           136:         if (getPointerContext.InputCount != 0) {
        !           137:         
        !           138:             //
        !           139:             // Call the connected class driver's callback ISR with the
        !           140:             // port InputData queue pointers.  If we have to wrap the queue,
        !           141:             // break the operation into two pieces, and call the class 
        !           142:             // callback ISR once for each piece.
        !           143:             //
        !           144:         
        !           145:             classDeviceObject =
        !           146:                 deviceExtension->KeyboardExtension.ConnectData.ClassDeviceObject;
        !           147:             classService =
        !           148:                 deviceExtension->KeyboardExtension.ConnectData.ClassService;
        !           149:             ASSERT(classService != NULL);
        !           150:         
        !           151:             if (getPointerContext.DataOut >= getPointerContext.DataIn) {
        !           152:         
        !           153:                 //
        !           154:                 // We'll have to wrap the InputData circular buffer.  Call
        !           155:                 // the class callback ISR with the chunk of data starting at 
        !           156:                 // DataOut and ending at the end of the queue.
        !           157:                 //
        !           158:         
        !           159:                 I8xPrint((
        !           160:                     2, 
        !           161:                     "I8042PRT-I8042KeyboardIsrDpc: calling class callback\n"
        !           162:                     ));
        !           163:                 I8xPrint((
        !           164:                     2,
        !           165:                     "I8042PRT-I8042KeyboardIsrDpc: with Start 0x%x and End 0x%x\n",
        !           166:                     getPointerContext.DataOut,
        !           167:                     deviceExtension->KeyboardExtension.DataEnd
        !           168:                     ));
        !           169:         
        !           170:                 (*(PSERVICE_CALLBACK_ROUTINE) classService)(
        !           171:                       classDeviceObject,
        !           172:                       getPointerContext.DataOut,
        !           173:                       deviceExtension->KeyboardExtension.DataEnd,
        !           174:                       &inputDataConsumed
        !           175:                       );
        !           176:         
        !           177:                 dataNotConsumed = (((PUCHAR)
        !           178:                     deviceExtension->KeyboardExtension.DataEnd -
        !           179:                     (PUCHAR) getPointerContext.DataOut) 
        !           180:                     / sizeof(KEYBOARD_INPUT_DATA)) - inputDataConsumed;
        !           181: 
        !           182:                 I8xPrint((
        !           183:                     2,
        !           184:                     "I8042PRT-I8042KeyboardIsrDpc: (Wrap) Call callback consumed %d items, left %d\n",
        !           185:                     inputDataConsumed,
        !           186:                     dataNotConsumed
        !           187:                     ));
        !           188: 
        !           189:                 setPointerContext.InputCount += inputDataConsumed;
        !           190:         
        !           191:                 if (dataNotConsumed) {
        !           192:                     setPointerContext.DataOut = 
        !           193:                         ((PUCHAR)getPointerContext.DataOut) + 
        !           194:                         (inputDataConsumed * sizeof(KEYBOARD_INPUT_DATA));
        !           195:                 } else {
        !           196:                     setPointerContext.DataOut =
        !           197:                         deviceExtension->KeyboardExtension.InputData;
        !           198:                     getPointerContext.DataOut = setPointerContext.DataOut;
        !           199:                 }
        !           200:             }
        !           201:         
        !           202:             //
        !           203:             // Call the class callback ISR with data remaining in the queue.
        !           204:             //
        !           205:         
        !           206:             if ((dataNotConsumed == 0) &&
        !           207:                 (inputDataConsumed < getPointerContext.InputCount)){
        !           208:                 I8xPrint((
        !           209:                     2, 
        !           210:                     "I8042PRT-I8042KeyboardIsrDpc: calling class callback\n"
        !           211:                     ));
        !           212:                 I8xPrint((
        !           213:                     2,
        !           214:                     "I8042PRT-I8042KeyboardIsrDpc: with Start 0x%x and End 0x%x\n",
        !           215:                     getPointerContext.DataOut,
        !           216:                     getPointerContext.DataIn
        !           217:                     ));
        !           218:         
        !           219:                 (*(PSERVICE_CALLBACK_ROUTINE) classService)(
        !           220:                       classDeviceObject,
        !           221:                       getPointerContext.DataOut,
        !           222:                       getPointerContext.DataIn,
        !           223:                       &inputDataConsumed
        !           224:                       );
        !           225: 
        !           226:                 dataNotConsumed = (((PUCHAR) getPointerContext.DataIn - 
        !           227:                       (PUCHAR) getPointerContext.DataOut)
        !           228:                       / sizeof(KEYBOARD_INPUT_DATA)) - inputDataConsumed;
        !           229:         
        !           230:                 I8xPrint((
        !           231:                     2,
        !           232:                     "I8042PRT-I8042KeyboardIsrDpc: Call callback consumed %d items, left %d\n",
        !           233:                     inputDataConsumed,
        !           234:                     dataNotConsumed
        !           235:                     ));
        !           236: 
        !           237:                 setPointerContext.DataOut = 
        !           238:                     ((PUCHAR)getPointerContext.DataOut) +
        !           239:                     (inputDataConsumed * sizeof(KEYBOARD_INPUT_DATA));
        !           240:                 setPointerContext.InputCount += inputDataConsumed;
        !           241: 
        !           242:             }
        !           243:         
        !           244:             //
        !           245:             // Update the port InputData queue DataOut pointer and InputCount
        !           246:             // synchronously.
        !           247:             //
        !           248:         
        !           249:             KeSynchronizeExecution(
        !           250:                 deviceExtension->KeyboardInterruptObject,
        !           251:                 (PKSYNCHRONIZE_ROUTINE) I8xSetDataQueuePointer,
        !           252:                 (PVOID) &setPointerContext
        !           253:                 );
        !           254:         
        !           255:         }
        !           256: 
        !           257:         if (dataNotConsumed) {
        !           258: 
        !           259:             //
        !           260:             // The class driver was unable to consume all the data.  
        !           261:             // Reset the interlocked variable to -1.  We do not want
        !           262:             // to attempt to move more data to the class driver at this
        !           263:             // point, because it is already overloaded.  Need to wait a
        !           264:             // while to give the Raw Input Thread a chance to read some
        !           265:             // of the data out of the class driver's queue.  We accomplish
        !           266:             // this "wait" via a timer.
        !           267:             // 
        !           268: 
        !           269:             I8xPrint((2, "I8042PRT-I8042KeyboardIsrDpc: set timer in DPC\n"));
        !           270: 
        !           271:             operationContext.Operation = WriteOperation;
        !           272:             interlockedResult = -1;
        !           273:             operationContext.NewValue = &interlockedResult;
        !           274:         
        !           275:             KeSynchronizeExecution(
        !           276:                     deviceExtension->KeyboardInterruptObject,
        !           277:                     (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
        !           278:                     (PVOID) &operationContext
        !           279:                     );
        !           280: 
        !           281:             deltaTime.LowPart = (ULONG)(-10 * 1000 * 1000);
        !           282:             deltaTime.HighPart = -1;
        !           283: 
        !           284:             (VOID) KeSetTimer(
        !           285:                        &deviceExtension->KeyboardExtension.DataConsumptionTimer,
        !           286:                        deltaTime,
        !           287:                        &deviceExtension->KeyboardIsrDpcRetry
        !           288:                        );
        !           289: 
        !           290:             moreDpcProcessing = FALSE; 
        !           291: 
        !           292:         } else {
        !           293:     
        !           294:             //
        !           295:             // Decrement DpcInterlockKeyboard.  If the result goes negative,
        !           296:             // then we're all finished processing the DPC.  Otherwise, either
        !           297:             // the ISR incremented DpcInterlockKeyboard because it has more
        !           298:             // work for the ISR DPC to do, or a concurrent DPC executed on 
        !           299:             // some processor while the current DPC was running (the 
        !           300:             // concurrent DPC wouldn't have done any work).  Make sure that 
        !           301:             // the current DPC handles any extra work that is ready to be
        !           302:             // done.
        !           303:             //
        !           304: 
        !           305:             operationContext.Operation = DecrementOperation;
        !           306:             operationContext.NewValue = &interlockedResult;
        !           307:         
        !           308:             KeSynchronizeExecution(
        !           309:                     deviceExtension->KeyboardInterruptObject,
        !           310:                     (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
        !           311:                     (PVOID) &operationContext
        !           312:                     );
        !           313: 
        !           314:             if (interlockedResult != -1) {
        !           315: 
        !           316:                 //
        !           317:                 // The interlocked variable is still greater than or equal to
        !           318:                 // zero. Reset it to zero, so that we execute the loop one
        !           319:                 // more time (assuming no more DPCs execute and bump the
        !           320:                 // variable up again).
        !           321:                 //
        !           322: 
        !           323:                 operationContext.Operation = WriteOperation;
        !           324:                 interlockedResult = 0;
        !           325:                 operationContext.NewValue = &interlockedResult;
        !           326:         
        !           327:                 KeSynchronizeExecution(
        !           328:                     deviceExtension->KeyboardInterruptObject,
        !           329:                     (PKSYNCHRONIZE_ROUTINE) I8xDpcVariableOperation,
        !           330:                     (PVOID) &operationContext
        !           331:                     );
        !           332: 
        !           333:                 I8xPrint((2, "I8042PRT-I8042KeyboardIsrDpc: loop in DPC\n"));
        !           334:             } else {
        !           335:                 moreDpcProcessing = FALSE;
        !           336:             }
        !           337:         }
        !           338: 
        !           339:     }
        !           340: 
        !           341:     I8xPrint((2, "I8042PRT-I8042KeyboardIsrDpc: exit\n"));
        !           342: 
        !           343: }
        !           344: 
        !           345: BOOLEAN
        !           346: I8xWriteDataToKeyboardQueue(
        !           347:     PPORT_KEYBOARD_EXTENSION KeyboardExtension,
        !           348:     IN PKEYBOARD_INPUT_DATA InputData
        !           349:     )
        !           350: 
        !           351: /*++
        !           352: 
        !           353: Routine Description:
        !           354: 
        !           355:     This routine adds input data from the keyboard to the InputData queue.
        !           356: 
        !           357: Arguments:
        !           358: 
        !           359:     KeyboardExtension - Pointer to the keyboard portion of the device extension.
        !           360: 
        !           361:     InputData - Pointer to the data to add to the InputData queue.
        !           362: 
        !           363: Return Value:
        !           364: 
        !           365:     Returns TRUE if the data was added, otherwise FALSE.
        !           366: 
        !           367: --*/
        !           368: 
        !           369: {
        !           370: 
        !           371:     PKEYBOARD_INPUT_DATA previousDataIn;
        !           372: 
        !           373:     I8xPrint((2,"I8042PRT-I8xWriteDataToKeyboardQueue: enter\n"));
        !           374:     I8xPrint((
        !           375:         3,
        !           376:         "I8042PRT-I8xWriteDataToKeyboardQueue: DataIn 0x%x, DataOut 0x%x\n",
        !           377:         KeyboardExtension->DataIn,
        !           378:         KeyboardExtension->DataOut
        !           379:         ));
        !           380:     I8xPrint((
        !           381:         3,
        !           382:         "I8042PRT-I8xWriteDataToKeyboardQueue: InputCount %d\n",
        !           383:         KeyboardExtension->InputCount
        !           384:         ));
        !           385: 
        !           386:     //
        !           387:     // Check for full input data queue.
        !           388:     //
        !           389: 
        !           390:     if ((KeyboardExtension->DataIn == KeyboardExtension->DataOut) &&
        !           391:         (KeyboardExtension->InputCount != 0)) {
        !           392: 
        !           393:         //
        !           394:         // Queue overflow.  Replace the previous input data packet
        !           395:         // with a keyboard overrun data packet, thus losing both the
        !           396:         // previous and the current input data packet.
        !           397:         //
        !           398: 
        !           399:         I8xPrint((1,"I8042PRT-I8xWriteDataToKeyboardQueue: OVERFLOW\n"));
        !           400: 
        !           401:         if (KeyboardExtension->DataIn == KeyboardExtension->InputData) {
        !           402:             I8xPrint((2,"I8042PRT-I8xWriteDataToKeyboardQueue: wrap buffer\n"));
        !           403:             previousDataIn = KeyboardExtension->DataEnd;
        !           404:         } else {
        !           405:             previousDataIn = KeyboardExtension->DataIn - 1;
        !           406:         }
        !           407: 
        !           408:         previousDataIn->MakeCode = KEYBOARD_OVERRUN_MAKE_CODE;
        !           409:         previousDataIn->Flags = 0;
        !           410: 
        !           411:         I8xPrint((2,"I8042PRT-I8xWriteDataToKeyboardQueue: exit\n"));
        !           412:         return(FALSE);
        !           413: 
        !           414:     } else {
        !           415:         *(KeyboardExtension->DataIn) = *InputData;
        !           416:         KeyboardExtension->InputCount += 1;
        !           417:         KeyboardExtension->DataIn++;
        !           418:         I8xPrint((
        !           419:             2,
        !           420:             "I8042PRT-I8xWriteDataToKeyboardQueue: new InputCount %d\n",
        !           421:             KeyboardExtension->InputCount
        !           422:             ));
        !           423:         if (KeyboardExtension->DataIn ==
        !           424:             KeyboardExtension->DataEnd) {
        !           425:             I8xPrint((2,"I8042PRT-I8xWriteDataToKeyboardQueue: wrap buffer\n"));
        !           426:             KeyboardExtension->DataIn = KeyboardExtension->InputData;
        !           427:         }
        !           428:     }
        !           429: 
        !           430:     I8xPrint((2,"I8042PRT-I8xWriteDataToKeyboardQueue: exit\n"));
        !           431: 
        !           432:     return(TRUE);
        !           433: }
        !           434: 

unix.superglobalmegacorp.com

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