Annotation of ntddk/src/comm/serial/openclos.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:     openclos.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This module contains the code that is very specific to
                     12:     opening, closing, and cleaning up 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: 
                     33: BOOLEAN
                     34: SerialMarkOpen(
                     35:     IN PVOID Context
                     36:     );
                     37: 
                     38: BOOLEAN
                     39: SerialCheckOpen(
                     40:     IN PVOID Context
                     41:     );
                     42: 
                     43: typedef struct _SERIAL_CHECK_OPEN {
                     44:     PSERIAL_DEVICE_EXTENSION Extension;
                     45:     NTSTATUS *StatusOfOpen;
                     46:     } SERIAL_CHECK_OPEN,*PSERIAL_CHECK_OPEN;
                     47: 
                     48: //
                     49: // Just a bogus little routine to make sure that we
                     50: // can synch with the ISR.
                     51: //
                     52: BOOLEAN
                     53: SerialNullSynch(
                     54:     IN PVOID Context
                     55:     ) {
                     56: 
                     57:     UNREFERENCED_PARAMETER(Context);
                     58:     return FALSE;
                     59: }
                     60: 
                     61: NTSTATUS
                     62: SerialCreateOpen(
                     63:     IN PDEVICE_OBJECT DeviceObject,
                     64:     IN PIRP Irp
                     65:     )
                     66: 
                     67: /*++
                     68: 
                     69: Routine Description:
                     70: 
                     71:     We connect up to the interrupt for the create/open and initialize
                     72:     the structures needed to maintain an open for a device.
                     73: 
                     74: Arguments:
                     75: 
                     76:     DeviceObject - Pointer to the device object for this device
                     77: 
                     78:     Irp - Pointer to the IRP for the current request
                     79: 
                     80: Return Value:
                     81: 
                     82:     The function value is the final status of the call
                     83: 
                     84: --*/
                     85: 
                     86: {
                     87: 
                     88:     PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
                     89:     SERIAL_CHECK_OPEN checkOpen;
                     90:     NTSTATUS localStatus;
                     91: 
                     92:     SerialDump(
                     93:         SERIRPPATH,
                     94:         ("SERIAL: Dispatch entry for: %x\n",Irp)
                     95:         );
                     96:     SerialDump(
                     97:         SERDIAG3,
                     98:         ("SERIAL: In SerialCreateOpen\n")
                     99:         );
                    100: 
                    101:     //
                    102:     // Before we do anything, let's make sure they aren't trying
                    103:     // to create a directory.  This is a silly, but what's a driver to do!?
                    104:     //
                    105: 
                    106:     if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Create.Options &
                    107:         FILE_DIRECTORY_FILE) {
                    108: 
                    109:         Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
                    110:         Irp->IoStatus.Information = 0;
                    111: 
                    112:         SerialDump(
                    113:             SERIRPPATH,
                    114:             ("SERIAL: Complete Irp: %x\n",Irp)
                    115:             );
                    116:         IoCompleteRequest(
                    117:             Irp,
                    118:             IO_NO_INCREMENT
                    119:             );
                    120:         return STATUS_NOT_A_DIRECTORY;
                    121: 
                    122:     }
                    123: 
                    124:     //
                    125:     // Create a buffer for the RX data when no reads are outstanding.
                    126:     //
                    127: 
                    128:     extension->InterruptReadBuffer = NULL;
                    129:     extension->BufferSize = 0;
                    130: 
                    131:     switch (MmQuerySystemSize()) {
                    132: 
                    133:         case MmLargeSystem: {
                    134: 
                    135:             extension->BufferSize = 4096;
                    136:             extension->InterruptReadBuffer = ExAllocatePool(
                    137:                                                  NonPagedPool,
                    138:                                                  extension->BufferSize
                    139:                                                  );
                    140: 
                    141:             if (extension->InterruptReadBuffer) {
                    142: 
                    143:                 break;
                    144: 
                    145:             }
                    146: 
                    147:         }
                    148: 
                    149:         case MmMediumSystem: {
                    150: 
                    151:             extension->BufferSize = 1024;
                    152:             extension->InterruptReadBuffer = ExAllocatePool(
                    153:                                                  NonPagedPool,
                    154:                                                  extension->BufferSize
                    155:                                                  );
                    156: 
                    157:             if (extension->InterruptReadBuffer) {
                    158: 
                    159:                 break;
                    160: 
                    161:             }
                    162: 
                    163:         }
                    164: 
                    165:         case MmSmallSystem: {
                    166: 
                    167:             extension->BufferSize = 128;
                    168:             extension->InterruptReadBuffer = ExAllocatePool(
                    169:                                                  NonPagedPool,
                    170:                                                  extension->BufferSize
                    171:                                                  );
                    172: 
                    173:         }
                    174: 
                    175:     }
                    176: 
                    177:     if (!extension->InterruptReadBuffer) {
                    178: 
                    179:         extension->BufferSize = 0;
                    180:         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    181:         Irp->IoStatus.Information = 0;
                    182: 
                    183:         SerialDump(
                    184:             SERIRPPATH,
                    185:             ("SERIAL: Complete Irp: %x\n",Irp)
                    186:             );
                    187:         IoCompleteRequest(
                    188:             Irp,
                    189:             IO_NO_INCREMENT
                    190:             );
                    191:         return STATUS_INSUFFICIENT_RESOURCES;
                    192: 
                    193:     }
                    194: 
                    195:     //
                    196:     // On a new open we "flush" the read queue by initializing the
                    197:     // count of characters.
                    198:     //
                    199: 
                    200:     extension->CharsInInterruptBuffer = 0;
                    201:     extension->LastCharSlot = extension->InterruptReadBuffer +
                    202:                               (extension->BufferSize - 1);
                    203: 
                    204:     extension->ReadBufferBase = extension->InterruptReadBuffer;
                    205:     extension->CurrentCharSlot = extension->InterruptReadBuffer;
                    206:     extension->FirstReadableChar = extension->InterruptReadBuffer;
                    207: 
                    208:     extension->TotalCharsQueued = 0;
                    209: 
                    210:     //
                    211:     // We set up the default xon/xoff limits.
                    212:     //
                    213: 
                    214:     extension->HandFlow.XoffLimit = extension->BufferSize >> 3;
                    215:     extension->HandFlow.XonLimit = extension->BufferSize >> 1;
                    216: 
                    217:     extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+
                    218:                                    (extension->BufferSize>>4));
                    219: 
                    220:     extension->IrpMaskLocation = NULL;
                    221:     extension->HistoryMask = 0;
                    222:     extension->IsrWaitMask = 0;
                    223: 
                    224:     extension->SendXonChar = FALSE;
                    225:     extension->SendXoffChar = FALSE;
                    226: 
                    227:     //
                    228:     // The escape char replacement must be reset upon every open.
                    229:     //
                    230: 
                    231:     extension->EscapeChar = 0;
                    232: 
                    233: #if !defined(SERIAL_CRAZY_INTERRUPTS)
                    234: 
                    235:     if (!extension->InterruptShareable) {
                    236: 
                    237:         checkOpen.Extension = extension;
                    238:         checkOpen.StatusOfOpen = &Irp->IoStatus.Status;
                    239: 
                    240:         KeSynchronizeExecution(
                    241:             extension->Interrupt,
                    242:             SerialCheckOpen,
                    243:             &checkOpen
                    244:             );
                    245: 
                    246:     } else {
                    247: 
                    248:         KeSynchronizeExecution(
                    249:             extension->Interrupt,
                    250:             SerialMarkOpen,
                    251:             extension
                    252:             );
                    253: 
                    254:         Irp->IoStatus.Status = STATUS_SUCCESS;
                    255: 
                    256:     }
                    257: #else
                    258: 
                    259:     //
                    260:     // Synchronize with the ISR and let it know that the device
                    261:     // has been successfully opened.
                    262:     //
                    263: 
                    264:     KeSynchronizeExecution(
                    265:         extension->Interrupt,
                    266:         SerialMarkOpen,
                    267:         extension
                    268:         );
                    269: 
                    270:     Irp->IoStatus.Status = STATUS_SUCCESS;
                    271: #endif
                    272: 
                    273:     localStatus = Irp->IoStatus.Status;
                    274:     Irp->IoStatus.Information=0L;
                    275: 
                    276:     SerialDump(
                    277:         SERIRPPATH,
                    278:         ("SERIAL: Complete Irp: %x\n",Irp)
                    279:         );
                    280:     IoCompleteRequest(
                    281:         Irp,
                    282:         IO_NO_INCREMENT
                    283:         );
                    284: 
                    285:     return localStatus;
                    286: 
                    287: }
                    288: 
                    289: NTSTATUS
                    290: SerialClose(
                    291:     IN PDEVICE_OBJECT DeviceObject,
                    292:     IN PIRP Irp
                    293:     )
                    294: 
                    295: /*++
                    296: 
                    297: Routine Description:
                    298: 
                    299:     We simpley disconnect the interrupt for now.
                    300: 
                    301: Arguments:
                    302: 
                    303:     DeviceObject - Pointer to the device object for this device
                    304: 
                    305:     Irp - Pointer to the IRP for the current request
                    306: 
                    307: Return Value:
                    308: 
                    309:     The function value is the final status of the call
                    310: 
                    311: --*/
                    312: 
                    313: {
                    314: 
                    315:     //
                    316:     // This "timer value" is used to wait 10 character times
                    317:     // after the hardware is empty before we actually "run down"
                    318:     // all of the flow control/break junk.
                    319:     //
                    320:     LARGE_INTEGER tenCharDelay;
                    321: 
                    322:     //
                    323:     // Holds a character time.
                    324:     //
                    325:     LARGE_INTEGER charTime;
                    326: 
                    327:     //
                    328:     // Just what it says.  This is the serial specific device
                    329:     // extension of the device object create for the serial driver.
                    330:     //
                    331:     PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
                    332: 
                    333:     SerialDump(
                    334:         SERIRPPATH,
                    335:         ("SERIAL: Dispatch entry for: %x\n",Irp)
                    336:         );
                    337:     SerialDump(
                    338:         SERDIAG3,
                    339:         ("SERIAL: In SerialClose\n")
                    340:         );
                    341: 
                    342:     charTime = RtlLargeIntegerNegate(SerialGetCharTime(extension));
                    343: 
                    344:     //
                    345:     // Synchronize with the ISR to let it know that interrupts are
                    346:     // no longer important.
                    347:     //
                    348: 
                    349:     KeSynchronizeExecution(
                    350:         extension->Interrupt,
                    351:         SerialMarkClose,
                    352:         extension
                    353:         );
                    354: 
                    355:     //
                    356:     // Synchronize with the isr to turn off break if it
                    357:     // is already on.
                    358:     //
                    359: 
                    360:     KeSynchronizeExecution(
                    361:         extension->Interrupt,
                    362:         SerialTurnOffBreak,
                    363:         extension
                    364:         );
                    365: 
                    366:     //
                    367:     // If the driver has automatically transmitted an Xoff in
                    368:     // the context of automatic receive flow control then we
                    369:     // should transmit an Xon.
                    370:     //
                    371: 
                    372:     if (extension->RXHolding & SERIAL_RX_XOFF) {
                    373: 
                    374:         //
                    375:         // Loop until the holding register is empty.
                    376:         //
                    377: 
                    378:         while (!(READ_LINE_STATUS(extension->Controller) &
                    379:                  SERIAL_LSR_THRE)) {
                    380: 
                    381:             KeDelayExecutionThread(
                    382:                 KernelMode,
                    383:                 FALSE,
                    384:                 &charTime
                    385:                 );
                    386: 
                    387:         }
                    388: 
                    389:         WRITE_TRANSMIT_HOLDING(
                    390:             extension->Controller,
                    391:             extension->SpecialChars.XonChar
                    392:             );
                    393: 
                    394:     }
                    395: 
                    396:     //
                    397:     // Wait until all characters have been emptied out of the hardware.
                    398:     //
                    399: 
                    400:     while ((READ_LINE_STATUS(extension->Controller) &
                    401:             (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) !=
                    402:             (SERIAL_LSR_THRE | SERIAL_LSR_TEMT)) {
                    403: 
                    404:         KeDelayExecutionThread(
                    405:             KernelMode,
                    406:             FALSE,
                    407:             &charTime
                    408:             );
                    409: 
                    410:     }
                    411: 
                    412:     //
                    413:     // The hardware is empty.  Delay 10 character times before
                    414:     // shut down all the flow control.
                    415:     //
                    416: 
                    417:     tenCharDelay = RtlExtendedIntegerMultiply(
                    418:                        charTime,
                    419:                        10
                    420:                        );
                    421: 
                    422:     KeDelayExecutionThread(
                    423:         KernelMode,
                    424:         TRUE,
                    425:         &tenCharDelay
                    426:         );
                    427: 
                    428:     SerialClrDTR(extension);
                    429: 
                    430:     //
                    431:     // We have to be very careful how we clear the RTS line.
                    432:     // Transmit toggling might have been on at some point.
                    433:     //
                    434:     // We know that there is nothing left that could start
                    435:     // out the "polling"  execution path.  We need to
                    436:     // check the counter that indicates that the execution
                    437:     // path is active.  If it is then we loop delaying one
                    438:     // character time.  After each delay we check to see if
                    439:     // the counter has gone to zero.  When it has we know that
                    440:     // the execution path should be just about finished.  We
                    441:     // make sure that we still aren't in the routine that
                    442:     // synchronized execution with the ISR by synchronizing
                    443:     // ourselve with the ISR.
                    444:     //
                    445: 
                    446:     if (extension->CountOfTryingToLowerRTS) {
                    447: 
                    448:         do {
                    449: 
                    450:             KeDelayExecutionThread(
                    451:                 KernelMode,
                    452:                 FALSE,
                    453:                 &charTime
                    454:                 );
                    455: 
                    456:         } while (extension->CountOfTryingToLowerRTS);
                    457: 
                    458:         KeSynchronizeExecution(
                    459:             extension->Interrupt,
                    460:             SerialNullSynch,
                    461:             NULL
                    462:             );
                    463: 
                    464:         //
                    465:         // The execution path should no longer exist that
                    466:         // is trying to push down the RTS.  Well just
                    467:         // make sure it's down by falling through to
                    468:         // code that forces it down.
                    469:         //
                    470: 
                    471:     }
                    472: 
                    473:     SerialClrRTS(extension);
                    474: 
                    475:     //
                    476:     // Clean out the holding reasons (since we are closed).
                    477:     //
                    478: 
                    479:     extension->RXHolding = 0;
                    480:     extension->TXHolding = 0;
                    481: 
                    482:     //
                    483:     // All is done.  The port has been disabled from interrupting
                    484:     // so there is no point in keeping the memory around.
                    485:     //
                    486: 
                    487:     extension->BufferSize = 0;
                    488:     ExFreePool(extension->InterruptReadBuffer);
                    489:     extension->InterruptReadBuffer = NULL;
                    490: 
                    491:     Irp->IoStatus.Status = STATUS_SUCCESS;
                    492:     Irp->IoStatus.Information=0L;
                    493: 
                    494:     SerialDump(
                    495:         SERIRPPATH,
                    496:         ("SERIAL: Complete Irp: %x\n",Irp)
                    497:         );
                    498:     IoCompleteRequest(
                    499:         Irp,
                    500:         IO_NO_INCREMENT
                    501:         );
                    502: 
                    503:     return STATUS_SUCCESS;
                    504: 
                    505: }
                    506: 
                    507: BOOLEAN
                    508: SerialCheckOpen(
                    509:     IN PVOID Context
                    510:     )
                    511: 
                    512: /*++
                    513: 
                    514: Routine Description:
                    515: 
                    516:     This routine will traverse the circular doubly linked list
                    517:     of devices that are using the same interrupt object.  It will look
                    518:     for other devices that are open.  If it doesn't find any
                    519:     it will indicate that it is ok to open this device.
                    520: 
                    521:     If it finds another device open we have two cases:
                    522: 
                    523:         1) The device we are trying to open is on a multiport card.
                    524: 
                    525:            If the already open device is part of a multiport device
                    526:            this code will indicate it is ok to open.  We do this on the
                    527:            theory that the multiport devices are daisy chained
                    528:            and the cards can correctly arbitrate the interrupt
                    529:            line.  Note this assumption could be wrong.  Somebody
                    530:            could put two non-daisychained multiports on the
                    531:            same interrupt.  However, only a total clod would do
                    532:            such a thing, and in my opinion deserves everthing they
                    533:            get.
                    534: 
                    535:         2) The device we are trying to open is not on a multiport card.
                    536: 
                    537:             We indicate that it is not ok to open.
                    538: 
                    539: Arguments:
                    540: 
                    541:     Context - This is a structure that contains a pointer to the
                    542:               extension of the device we are trying to open, and
                    543:               a pointer to an NTSTATUS that will indicate whether
                    544:               the device was opened or not.
                    545: 
                    546: Return Value:
                    547: 
                    548:     This routine always returns FALSE.
                    549: 
                    550: --*/
                    551: 
                    552: {
                    553: 
                    554:     PSERIAL_DEVICE_EXTENSION extensionToOpen =
                    555:         ((PSERIAL_CHECK_OPEN)Context)->Extension;
                    556:     NTSTATUS *status = ((PSERIAL_CHECK_OPEN)Context)->StatusOfOpen;
                    557:     PLIST_ENTRY firstEntry = &extensionToOpen->CommonInterruptObject;
                    558:     PLIST_ENTRY currentEntry = firstEntry;
                    559:     PSERIAL_DEVICE_EXTENSION currentExtension;
                    560: 
                    561:     do {
                    562: 
                    563:         currentExtension = CONTAINING_RECORD(
                    564:                                currentEntry,
                    565:                                SERIAL_DEVICE_EXTENSION,
                    566:                                CommonInterruptObject
                    567:                                );
                    568: 
                    569:         if (currentExtension->DeviceIsOpened) {
                    570: 
                    571:             break;
                    572: 
                    573:         }
                    574: 
                    575:         currentEntry = currentExtension->CommonInterruptObject.Flink;
                    576: 
                    577:     } while (currentEntry != firstEntry);
                    578: 
                    579:     if (currentEntry == firstEntry) {
                    580: 
                    581:         //
                    582:         // We searched the whole list and found no other opens
                    583:         // mark the status as successful and call the regular
                    584:         // opening routine.
                    585:         //
                    586: 
                    587:         *status = STATUS_SUCCESS;
                    588:         SerialMarkOpen(extensionToOpen);
                    589: 
                    590:     } else {
                    591: 
                    592:         if (!extensionToOpen->PortOnAMultiportCard) {
                    593: 
                    594:             *status = STATUS_SHARED_IRQ_BUSY;
                    595: 
                    596:         } else {
                    597: 
                    598:             if (!currentExtension->PortOnAMultiportCard) {
                    599: 
                    600:                 *status = STATUS_SHARED_IRQ_BUSY;
                    601: 
                    602:             } else {
                    603: 
                    604:                 *status = STATUS_SUCCESS;
                    605:                 SerialMarkOpen(extensionToOpen);
                    606: 
                    607:             }
                    608: 
                    609:         }
                    610: 
                    611:     }
                    612: 
                    613:     return FALSE;
                    614: 
                    615: }
                    616: 
                    617: BOOLEAN
                    618: SerialMarkOpen(
                    619:     IN PVOID Context
                    620:     )
                    621: 
                    622: /*++
                    623: 
                    624: Routine Description:
                    625: 
                    626:     This routine merely sets a boolean to true to mark the fact that
                    627:     somebody opened the device and its worthwhile to pay attention
                    628:     to interrupts.
                    629: 
                    630: Arguments:
                    631: 
                    632:     Context - Really a pointer to the device extension.
                    633: 
                    634: Return Value:
                    635: 
                    636:     This routine always returns FALSE.
                    637: 
                    638: --*/
                    639: 
                    640: {
                    641: 
                    642:     PSERIAL_DEVICE_EXTENSION extension = Context;
                    643: 
                    644:     SerialReset(extension);
                    645: 
                    646:     //
                    647:     // Prepare for the opening by re-enabling interrupts.
                    648:     //
                    649:     // We do this my modifying the OUT2 line in the modem control.
                    650:     // In PC's this bit is "anded" with the interrupt line.
                    651:     //
                    652:     // For the Jensen, we will ALWAYS leave the line high.  That's
                    653:     // the way the hardware engineers want it.
                    654:     //
                    655: 
                    656:     WRITE_MODEM_CONTROL(
                    657:         extension->Controller,
                    658:         (UCHAR)(READ_MODEM_CONTROL(extension->Controller) | SERIAL_MCR_OUT2)
                    659:         );
                    660: 
                    661:     extension->DeviceIsOpened = TRUE;
                    662:     extension->ErrorWord = 0;
                    663: 
                    664:     return FALSE;
                    665: 
                    666: }
                    667: 
                    668: BOOLEAN
                    669: SerialMarkClose(
                    670:     IN PVOID Context
                    671:     )
                    672: 
                    673: /*++
                    674: 
                    675: Routine Description:
                    676: 
                    677:     This routine merely sets a boolean to false to mark the fact that
                    678:     somebody closed the device and it's no longer worthwhile to pay attention
                    679:     to interrupts.
                    680: 
                    681: Arguments:
                    682: 
                    683:     Context - Really a pointer to the device extension.
                    684: 
                    685: Return Value:
                    686: 
                    687:     This routine always returns FALSE.
                    688: 
                    689: --*/
                    690: 
                    691: {
                    692: 
                    693:     PSERIAL_DEVICE_EXTENSION extension = Context;
                    694: 
                    695:     //
                    696:     // Prepare for the closing by stopping interrupts.
                    697:     //
                    698:     // We do this by adjusting the OUT2 line in the modem control.
                    699:     // In PC's this bit is "anded" with the interrupt line.
                    700:     //
                    701:     // The line should stay high on the Jensen because that's the
                    702:     // way the hardware engineers did it.
                    703:     //
                    704: 
                    705:     if (!extension->Jensen) {
                    706: 
                    707:         WRITE_MODEM_CONTROL(
                    708:             extension->Controller,
                    709:             (UCHAR)(READ_MODEM_CONTROL(extension->Controller) & ~SERIAL_MCR_OUT2)
                    710:             );
                    711: 
                    712:     }
                    713: 
                    714:     if (extension->FifoPresent) {
                    715: 
                    716:         WRITE_FIFO_CONTROL(
                    717:             extension->Controller,
                    718:             (UCHAR)0
                    719:             );
                    720: 
                    721:     }
                    722: 
                    723:     extension->DeviceIsOpened = FALSE;
                    724: 
                    725:     return FALSE;
                    726: 
                    727: }
                    728: 
                    729: NTSTATUS
                    730: SerialCleanup(
                    731:     IN PDEVICE_OBJECT DeviceObject,
                    732:     IN PIRP Irp
                    733:     )
                    734: 
                    735: /*++
                    736: 
                    737: Routine Description:
                    738: 
                    739:     This function is used to kill all longstanding IO operations.
                    740: 
                    741: Arguments:
                    742: 
                    743:     DeviceObject - Pointer to the device object for this device
                    744: 
                    745:     Irp - Pointer to the IRP for the current request
                    746: 
                    747: Return Value:
                    748: 
                    749:     The function value is the final status of the call
                    750: 
                    751: --*/
                    752: 
                    753: {
                    754: 
                    755:     PSERIAL_DEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
                    756:     KIRQL oldIrql;
                    757: 
                    758:     SerialDump(
                    759:         SERIRPPATH,
                    760:         ("SERIAL: Dispatch entry for: %x\n",Irp)
                    761:         );
                    762:     //
                    763:     // First kill all the reads and writes.
                    764:     //
                    765: 
                    766:     SerialKillAllReadsOrWrites(
                    767:         DeviceObject,
                    768:         &extension->WriteQueue,
                    769:         &extension->CurrentWriteIrp
                    770:         );
                    771: 
                    772:     SerialKillAllReadsOrWrites(
                    773:         DeviceObject,
                    774:         &extension->ReadQueue,
                    775:         &extension->CurrentReadIrp
                    776:         );
                    777: 
                    778:     //
                    779:     // Next get rid of purges.
                    780:     //
                    781: 
                    782:     SerialKillAllReadsOrWrites(
                    783:         DeviceObject,
                    784:         &extension->PurgeQueue,
                    785:         &extension->CurrentPurgeIrp
                    786:         );
                    787: 
                    788:     //
                    789:     // Get rid of any mask operations.
                    790:     //
                    791: 
                    792:     SerialKillAllReadsOrWrites(
                    793:         DeviceObject,
                    794:         &extension->MaskQueue,
                    795:         &extension->CurrentMaskIrp
                    796:         );
                    797: 
                    798:     //
                    799:     // Now get rid a pending wait mask irp.
                    800:     //
                    801: 
                    802:     IoAcquireCancelSpinLock(&oldIrql);
                    803: 
                    804:     if (extension->CurrentWaitIrp) {
                    805: 
                    806:         PDRIVER_CANCEL cancelRoutine;
                    807: 
                    808:         cancelRoutine = extension->CurrentWaitIrp->CancelRoutine;
                    809:         extension->CurrentWaitIrp->Cancel = TRUE;
                    810: 
                    811:         if (cancelRoutine) {
                    812: 
                    813:             extension->CurrentWaitIrp->CancelIrql = oldIrql;
                    814:             extension->CurrentWaitIrp->CancelRoutine = NULL;
                    815: 
                    816:             cancelRoutine(
                    817:                 DeviceObject,
                    818:                 extension->CurrentWaitIrp
                    819:                 );
                    820: 
                    821:         }
                    822: 
                    823:     } else {
                    824: 
                    825:         IoReleaseCancelSpinLock(oldIrql);
                    826: 
                    827:     }
                    828: 
                    829:     Irp->IoStatus.Status = STATUS_SUCCESS;
                    830:     Irp->IoStatus.Information=0L;
                    831: 
                    832:     SerialDump(
                    833:         SERIRPPATH,
                    834:         ("SERIAL: Complete Irp: %x\n",Irp)
                    835:         );
                    836:     IoCompleteRequest(
                    837:         Irp,
                    838:         IO_NO_INCREMENT
                    839:         );
                    840: 
                    841:     return STATUS_SUCCESS;
                    842: 
                    843: }
                    844: 
                    845: LARGE_INTEGER
                    846: SerialGetCharTime(
                    847:     IN PSERIAL_DEVICE_EXTENSION Extension
                    848:     )
                    849: 
                    850: /*++
                    851: 
                    852: Routine Description:
                    853: 
                    854:     This function will return the number of 100 nanosecond intervals
                    855:     there are in one character time (based on the present form
                    856:     of flow control.
                    857: 
                    858: Arguments:
                    859: 
                    860:     Extension - Just what it says.
                    861: 
                    862: Return Value:
                    863: 
                    864:     100 nanosecond intervals in a character time.
                    865: 
                    866: --*/
                    867: 
                    868: {
                    869: 
                    870:     ULONG dataSize;
                    871:     ULONG paritySize;
                    872:     ULONG stopSize;
                    873:     ULONG charTime;
                    874:     ULONG bitTime;
                    875: 
                    876: 
                    877:     if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) {
                    878:         dataSize = 5;
                    879:     } else if ((Extension->LineControl & SERIAL_DATA_MASK)
                    880:                 == SERIAL_6_DATA) {
                    881:         dataSize = 6;
                    882:     } else if ((Extension->LineControl & SERIAL_DATA_MASK)
                    883:                 == SERIAL_7_DATA) {
                    884:         dataSize = 7;
                    885:     } else if ((Extension->LineControl & SERIAL_DATA_MASK)
                    886:                 == SERIAL_8_DATA) {
                    887:         dataSize = 8;
                    888:     }
                    889: 
                    890:     paritySize = 1;
                    891:     if ((Extension->LineControl & SERIAL_PARITY_MASK)
                    892:             == SERIAL_NONE_PARITY) {
                    893: 
                    894:         paritySize = 0;
                    895: 
                    896:     }
                    897: 
                    898:     if (Extension->LineControl & SERIAL_2_STOP) {
                    899: 
                    900:         //
                    901:         // Even if it is 1.5, for sanities sake were going
                    902:         // to say 2.
                    903:         //
                    904: 
                    905:         stopSize = 2;
                    906: 
                    907:     } else {
                    908: 
                    909:         stopSize = 1;
                    910: 
                    911:     }
                    912: 
                    913:     //
                    914:     // First we calculate the number of 100 nanosecond intervals
                    915:     // are in a single bit time (Approximately).
                    916:     //
                    917: 
                    918:     bitTime = (10000000+(Extension->CurrentBaud-1))/Extension->CurrentBaud;
                    919:     charTime = bitTime + ((dataSize+paritySize+stopSize)*bitTime);
                    920: 
                    921:     return RtlConvertUlongToLargeInteger(charTime);
                    922: 
                    923: }

unix.superglobalmegacorp.com

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