Annotation of ntddk/src/comm/serial/openclos.c, revision 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.