Annotation of ntddk/src/comm/serial/immediat.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     immediat.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains the code that is very specific to transmit
                     12:     immediate character operations in the serial driver
                     13: 
                     14: Author:
                     15: 
                     16:     Anthony V. Ercolano 26-Sep-1991
                     17: 
                     18: Environment:
                     19: 
                     20:     Kernel mode
                     21: 
                     22: Revision History :
                     23: 
                     24: --*/
                     25: 
                     26: #include <stddef.h>
                     27: #include "ntddk.h"
                     28: #include "ntddser.h"
                     29: #include "serial.h"
                     30: #include "serialp.h"
                     31: 
                     32: VOID
                     33: SerialGetNextImmediate(
                     34:     IN PIRP *CurrentOpIrp,
                     35:     IN PLIST_ENTRY QueueToProcess,
                     36:     IN PIRP *NewIrp,
                     37:     IN BOOLEAN CompleteCurrent
                     38:     );
                     39: 
                     40: VOID
                     41: SerialCancelImmediate(
                     42:     IN PDEVICE_OBJECT DeviceObject,
                     43:     IN PIRP Irp
                     44:     );
                     45: 
                     46: BOOLEAN
                     47: SerialGiveImmediateToIsr(
                     48:     IN PVOID Context
                     49:     );
                     50: 
                     51: BOOLEAN
                     52: SerialGrabImmediateFromIsr(
                     53:     IN PVOID Context
                     54:     );
                     55: 
                     56: BOOLEAN
                     57: SerialGiveImmediateToIsr(
                     58:     IN PVOID Context
                     59:     );
                     60: 
                     61: BOOLEAN
                     62: SerialGrabImmediateFromIsr(
                     63:     IN PVOID Context
                     64:     );
                     65: 
                     66: 
                     67: VOID
                     68: SerialStartImmediate(
                     69:     IN PSERIAL_DEVICE_EXTENSION Extension
                     70:     )
                     71: 
                     72: /*++
                     73: 
                     74: Routine Description:
                     75: 
                     76:     This routine will calculate the timeouts needed for the
                     77:     write.  It will then hand the irp off to the isr.  It
                     78:     will need to be careful incase the irp has been canceled.
                     79: 
                     80: Arguments:
                     81: 
                     82:     Extension - A pointer to the serial device extension.
                     83: 
                     84: Return Value:
                     85: 
                     86:     None.
                     87: 
                     88: --*/
                     89: 
                     90: {
                     91: 
                     92:     KIRQL OldIrql;
                     93:     LARGE_INTEGER TotalTime;
                     94:     BOOLEAN UseATimer;
                     95:     SERIAL_TIMEOUTS Timeouts;
                     96: 
                     97: 
                     98:     UseATimer = FALSE;
                     99:     Extension->CurrentImmediateIrp->IoStatus.Status = STATUS_PENDING;
                    100:     IoMarkIrpPending(Extension->CurrentImmediateIrp);
                    101: 
                    102:     //
                    103:     // Calculate the timeout value needed for the
                    104:     // request.  Note that the values stored in the
                    105:     // timeout record are in milliseconds.  Note that
                    106:     // if the timeout values are zero then we won't start
                    107:     // the timer.
                    108:     //
                    109: 
                    110:     KeAcquireSpinLock(
                    111:         &Extension->ControlLock,
                    112:         &OldIrql
                    113:         );
                    114: 
                    115:     Timeouts = Extension->Timeouts;
                    116: 
                    117:     KeReleaseSpinLock(
                    118:         &Extension->ControlLock,
                    119:         OldIrql
                    120:         );
                    121: 
                    122:     if (Timeouts.WriteTotalTimeoutConstant ||
                    123:         Timeouts.WriteTotalTimeoutMultiplier) {
                    124: 
                    125:         UseATimer = TRUE;
                    126: 
                    127:         //
                    128:         // We have some timer values to calculate.
                    129:         //
                    130: 
                    131:         TotalTime = RtlEnlargedUnsignedMultiply(
                    132:                         1,
                    133:                         Timeouts.WriteTotalTimeoutMultiplier
                    134:                         );
                    135: 
                    136:         TotalTime = RtlLargeIntegerAdd(
                    137:                         TotalTime,
                    138:                         RtlConvertUlongToLargeInteger(
                    139:                             Timeouts.WriteTotalTimeoutConstant
                    140:                             )
                    141:                         );
                    142: 
                    143:         TotalTime = RtlExtendedIntegerMultiply(
                    144:                         TotalTime,
                    145:                         -10000
                    146:                         );
                    147: 
                    148:     }
                    149: 
                    150:     //
                    151:     // As the irp might be going to the isr, this is a good time
                    152:     // to initialize the reference count.
                    153:     //
                    154: 
                    155:     SERIAL_INIT_REFERENCE(Extension->CurrentImmediateIrp);
                    156: 
                    157:     //
                    158:     // We need to see if this irp should be canceled.
                    159:     //
                    160: 
                    161:     IoAcquireCancelSpinLock(&OldIrql);
                    162:     if (Extension->CurrentImmediateIrp->Cancel) {
                    163: 
                    164:         PIRP OldIrp = Extension->CurrentImmediateIrp;
                    165: 
                    166:         Extension->CurrentImmediateIrp = NULL;
                    167:         IoReleaseCancelSpinLock(OldIrql);
                    168: 
                    169:         OldIrp->IoStatus.Status = STATUS_CANCELLED;
                    170:         OldIrp->IoStatus.Information = 0;
                    171: 
                    172:         SerialDump(
                    173:             SERIRPPATH,
                    174:             ("SERIAL: Complete Irp: %x\n",OldIrp)
                    175:             );
                    176:         IoCompleteRequest(
                    177:             OldIrp,
                    178:             0
                    179:             );
                    180: 
                    181:     } else {
                    182: 
                    183:         //
                    184:         // We give the irp to to the isr to write out.
                    185:         // We set a cancel routine that knows how to
                    186:         // grab the current write away from the isr.
                    187:         //
                    188: 
                    189:         IoSetCancelRoutine(
                    190:             Extension->CurrentImmediateIrp,
                    191:             SerialCancelImmediate
                    192:             );
                    193: 
                    194:         //
                    195:         // Since the cancel routine knows about the irp we
                    196:         // increment the reference count.
                    197:         //
                    198: 
                    199:         SERIAL_INC_REFERENCE(Extension->CurrentImmediateIrp);
                    200: 
                    201:         if (UseATimer) {
                    202: 
                    203:             KeSetTimer(
                    204:                 &Extension->ImmediateTotalTimer,
                    205:                 TotalTime,
                    206:                 &Extension->TotalImmediateTimeoutDpc
                    207:                 );
                    208: 
                    209:             //
                    210:             // Since the timer knows about the irp we increment
                    211:             // the reference count.
                    212:             //
                    213: 
                    214:             SERIAL_INC_REFERENCE(Extension->CurrentImmediateIrp);
                    215: 
                    216:         }
                    217: 
                    218:         KeSynchronizeExecution(
                    219:             Extension->Interrupt,
                    220:             SerialGiveImmediateToIsr,
                    221:             Extension
                    222:             );
                    223: 
                    224:         IoReleaseCancelSpinLock(OldIrql);
                    225: 
                    226:     }
                    227: 
                    228: }
                    229: 
                    230: VOID
                    231: SerialCompleteImmediate(
                    232:     IN PKDPC Dpc,
                    233:     IN PVOID DeferredContext,
                    234:     IN PVOID SystemContext1,
                    235:     IN PVOID SystemContext2
                    236:     )
                    237: 
                    238: {
                    239: 
                    240:     PSERIAL_DEVICE_EXTENSION Extension = DeferredContext;
                    241:     KIRQL OldIrql;
                    242: 
                    243:     UNREFERENCED_PARAMETER(Dpc);
                    244:     UNREFERENCED_PARAMETER(SystemContext1);
                    245:     UNREFERENCED_PARAMETER(SystemContext2);
                    246: 
                    247:     IoAcquireCancelSpinLock(&OldIrql);
                    248: 
                    249:     SerialTryToCompleteCurrent(
                    250:         Extension,
                    251:         NULL,
                    252:         OldIrql,
                    253:         STATUS_SUCCESS,
                    254:         &Extension->CurrentImmediateIrp,
                    255:         NULL,
                    256:         NULL,
                    257:         &Extension->ImmediateTotalTimer,
                    258:         NULL,
                    259:         SerialGetNextImmediate
                    260:         );
                    261: 
                    262: }
                    263: 
                    264: VOID
                    265: SerialTimeoutImmediate(
                    266:     IN PKDPC Dpc,
                    267:     IN PVOID DeferredContext,
                    268:     IN PVOID SystemContext1,
                    269:     IN PVOID SystemContext2
                    270:     )
                    271: 
                    272: {
                    273: 
                    274:     PSERIAL_DEVICE_EXTENSION Extension = DeferredContext;
                    275:     KIRQL OldIrql;
                    276: 
                    277:     UNREFERENCED_PARAMETER(Dpc);
                    278:     UNREFERENCED_PARAMETER(SystemContext1);
                    279:     UNREFERENCED_PARAMETER(SystemContext2);
                    280: 
                    281:     IoAcquireCancelSpinLock(&OldIrql);
                    282: 
                    283:     SerialTryToCompleteCurrent(
                    284:         Extension,
                    285:         SerialGrabImmediateFromIsr,
                    286:         OldIrql,
                    287:         STATUS_TIMEOUT,
                    288:         &Extension->CurrentImmediateIrp,
                    289:         NULL,
                    290:         NULL,
                    291:         &Extension->ImmediateTotalTimer,
                    292:         NULL,
                    293:         SerialGetNextImmediate
                    294:         );
                    295: 
                    296: }
                    297: 
                    298: VOID
                    299: SerialGetNextImmediate(
                    300:     IN PIRP *CurrentOpIrp,
                    301:     IN PLIST_ENTRY QueueToProcess,
                    302:     IN PIRP *NewIrp,
                    303:     IN BOOLEAN CompleteCurrent
                    304:     )
                    305: 
                    306: /*++
                    307: 
                    308: Routine Description:
                    309: 
                    310:     This routine is used to complete the current immediate
                    311:     irp.  Even though the current immediate will always
                    312:     be completed and there is no queue associated with it,
                    313:     we use this routine so that we can try to satisfy
                    314:     a wait for transmit queue empty event.
                    315: 
                    316: Arguments:
                    317: 
                    318:     CurrentOpIrp - Pointer to the pointer that points to the
                    319:                    current write irp.  This should point
                    320:                    to CurrentImmediateIrp.
                    321: 
                    322:     QueueToProcess - Always NULL.
                    323: 
                    324:     NewIrp - Always NULL on exit to this routine.
                    325: 
                    326:     CompleteCurrent - Should always be true for this routine.
                    327: 
                    328: 
                    329: Return Value:
                    330: 
                    331:     None.
                    332: 
                    333: --*/
                    334: 
                    335: {
                    336: 
                    337:     KIRQL OldIrql;
                    338:     PSERIAL_DEVICE_EXTENSION Extension = CONTAINING_RECORD(
                    339:                                              CurrentOpIrp,
                    340:                                              SERIAL_DEVICE_EXTENSION,
                    341:                                              CurrentImmediateIrp
                    342:                                              );
                    343:     PIRP OldIrp = *CurrentOpIrp;
                    344: 
                    345:     UNREFERENCED_PARAMETER(QueueToProcess);
                    346:     UNREFERENCED_PARAMETER(CompleteCurrent);
                    347: 
                    348:     IoAcquireCancelSpinLock(&OldIrql);
                    349: 
                    350:     ASSERT(Extension->TotalCharsQueued >= 1);
                    351:     Extension->TotalCharsQueued--;
                    352: 
                    353:     *CurrentOpIrp = NULL;
                    354:     *NewIrp = NULL;
                    355:     KeSynchronizeExecution(
                    356:         Extension->Interrupt,
                    357:         SerialProcessEmptyTransmit,
                    358:         Extension
                    359:         );
                    360:     IoReleaseCancelSpinLock(OldIrql);
                    361: 
                    362:     SerialDump(
                    363:         SERIRPPATH,
                    364:         ("SERIAL: Complete Irp: %x\n",OldIrp)
                    365:         );
                    366:     IoCompleteRequest(
                    367:         OldIrp,
                    368:         IO_SERIAL_INCREMENT
                    369:         );
                    370: 
                    371: }
                    372: 
                    373: VOID
                    374: SerialCancelImmediate(
                    375:     IN PDEVICE_OBJECT DeviceObject,
                    376:     IN PIRP Irp
                    377:     )
                    378: 
                    379: /*++
                    380: 
                    381: Routine Description:
                    382: 
                    383:     This routine is used to cancel a irp that is waiting on
                    384:     a comm event.
                    385: 
                    386: Arguments:
                    387: 
                    388:     DeviceObject - Pointer to the device object for this device
                    389: 
                    390:     Irp - Pointer to the IRP for the current request
                    391: 
                    392: Return Value:
                    393: 
                    394:     None.
                    395: 
                    396: --*/
                    397: 
                    398: {
                    399: 
                    400:     PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
                    401: 
                    402:     SerialTryToCompleteCurrent(
                    403:         Extension,
                    404:         SerialGrabImmediateFromIsr,
                    405:         Irp->CancelIrql,
                    406:         STATUS_CANCELLED,
                    407:         &Extension->CurrentImmediateIrp,
                    408:         NULL,
                    409:         NULL,
                    410:         &Extension->ImmediateTotalTimer,
                    411:         NULL,
                    412:         SerialGetNextImmediate
                    413:         );
                    414: 
                    415: }
                    416: 
                    417: BOOLEAN
                    418: SerialGiveImmediateToIsr(
                    419:     IN PVOID Context
                    420:     )
                    421: 
                    422: /*++
                    423: 
                    424: Routine Description:
                    425: 
                    426:     Try to start off the write by slipping it in behind
                    427:     a transmit immediate char, or if that isn't available
                    428:     and the transmit holding register is empty, "tickle"
                    429:     the UART into interrupting with a transmit buffer
                    430:     empty.
                    431: 
                    432:     NOTE: This routine is called by KeSynchronizeExecution.
                    433: 
                    434:     NOTE: This routine assumes that it is called with the
                    435:           cancel spin lock held.
                    436: 
                    437: Arguments:
                    438: 
                    439:     Context - Really a pointer to the device extension.
                    440: 
                    441: Return Value:
                    442: 
                    443:     This routine always returns FALSE.
                    444: 
                    445: --*/
                    446: 
                    447: {
                    448: 
                    449:     PSERIAL_DEVICE_EXTENSION Extension = Context;
                    450: 
                    451:     Extension->TransmitImmediate = TRUE;
                    452:     Extension->ImmediateChar =
                    453:         *((UCHAR *)
                    454:          (Extension->CurrentImmediateIrp->AssociatedIrp.SystemBuffer));
                    455: 
                    456:     //
                    457:     // The isr now has a reference to the irp.
                    458:     //
                    459: 
                    460:     SERIAL_INC_REFERENCE(Extension->CurrentImmediateIrp);
                    461: 
                    462:     //
                    463:     // Check first to see if a write is going on.  If
                    464:     // there is then we'll just slip in during the write.
                    465:     //
                    466: 
                    467:     if (!Extension->WriteLength) {
                    468: 
                    469:         //
                    470:         // If there is no normal write transmitting then we
                    471:         // will "re-enable" the transmit holding register empty
                    472:         // interrupt.  The 8250 family of devices will always
                    473:         // signal a transmit holding register empty interrupt
                    474:         // *ANY* time this bit is set to one.  By doing things
                    475:         // this way we can simply use the normal interrupt code
                    476:         // to start off this write.
                    477:         //
                    478:         // We've been keeping track of whether the transmit holding
                    479:         // register is empty so it we only need to do this
                    480:         // if the register is empty.
                    481:         //
                    482: 
                    483:         if (Extension->HoldingEmpty) {
                    484: 
                    485:             DISABLE_ALL_INTERRUPTS(Extension->Controller);
                    486:             ENABLE_ALL_INTERRUPTS(Extension->Controller);
                    487: 
                    488:         }
                    489: 
                    490:     }
                    491: 
                    492:     return FALSE;
                    493: 
                    494: }
                    495: 
                    496: BOOLEAN
                    497: SerialGrabImmediateFromIsr(
                    498:     IN PVOID Context
                    499:     )
                    500: 
                    501: /*++
                    502: 
                    503: Routine Description:
                    504: 
                    505: 
                    506:     This routine is used to grab the current irp, which could be timing
                    507:     out or canceling, from the ISR
                    508: 
                    509:     NOTE: This routine is being called from KeSynchronizeExecution.
                    510: 
                    511:     NOTE: This routine assumes that the cancel spin lock is held
                    512:           when this routine is called.
                    513: 
                    514: Arguments:
                    515: 
                    516:     Context - Really a pointer to the device extension.
                    517: 
                    518: Return Value:
                    519: 
                    520:     Always false.
                    521: 
                    522: --*/
                    523: 
                    524: {
                    525: 
                    526:     PSERIAL_DEVICE_EXTENSION Extension = Context;
                    527: 
                    528:     if (Extension->TransmitImmediate) {
                    529: 
                    530:         Extension->TransmitImmediate = FALSE;
                    531: 
                    532:         //
                    533:         // Since the isr no longer references this irp, we can
                    534:         // decrement it's reference count.
                    535:         //
                    536: 
                    537:         SERIAL_DEC_REFERENCE(Extension->CurrentImmediateIrp);
                    538: 
                    539:     }
                    540: 
                    541:     return FALSE;
                    542: 
                    543: }

unix.superglobalmegacorp.com

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