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