Annotation of ntddk/src/comm/serial/ioctl.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     ioctl.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains the ioctl dispatcher as well as a couple
        !            12:     of routines that are generally just called in response to
        !            13:     ioctl calls.
        !            14: 
        !            15: Author:
        !            16: 
        !            17:     Anthony V. Ercolano 26-Sep-1991
        !            18: 
        !            19: Environment:
        !            20: 
        !            21:     Kernel mode
        !            22: 
        !            23: Revision History :
        !            24: 
        !            25: --*/
        !            26: 
        !            27: #include <stddef.h>
        !            28: #include "ntddk.h"
        !            29: #include "ntddser.h"
        !            30: #include "serial.h"
        !            31: #include "serialp.h"
        !            32: 
        !            33: BOOLEAN
        !            34: SerialGetModemUpdate(
        !            35:     IN PVOID Context
        !            36:     );
        !            37: 
        !            38: BOOLEAN
        !            39: SerialGetCommStatus(
        !            40:     IN PVOID Context
        !            41:     );
        !            42: 
        !            43: VOID
        !            44: SerialGetProperties(
        !            45:     IN PSERIAL_DEVICE_EXTENSION Extension,
        !            46:     IN PSERIAL_COMMPROP Properties
        !            47:     );
        !            48: 
        !            49: BOOLEAN
        !            50: SerialSetEscapeChar(
        !            51:     IN PVOID Context
        !            52:     );
        !            53: 
        !            54: 
        !            55: BOOLEAN
        !            56: SerialSetChars(
        !            57:     IN PVOID Context
        !            58:     )
        !            59: 
        !            60: /*++
        !            61: 
        !            62: Routine Description:
        !            63: 
        !            64:     This routine is used to set the special characters for the
        !            65:     driver.
        !            66: 
        !            67: Arguments:
        !            68: 
        !            69:     Context - Pointer to a structure that contains a pointer to
        !            70:               the device extension and a pointer to a special characters
        !            71:               structure.
        !            72: 
        !            73: Return Value:
        !            74: 
        !            75:     This routine always returns FALSE.
        !            76: 
        !            77: --*/
        !            78: 
        !            79: {
        !            80: 
        !            81:     ((PSERIAL_IOCTL_SYNC)Context)->Extension->SpecialChars =
        !            82:         *((PSERIAL_CHARS)(((PSERIAL_IOCTL_SYNC)Context)->Data));
        !            83: 
        !            84:     return FALSE;
        !            85: 
        !            86: }
        !            87: 
        !            88: BOOLEAN
        !            89: SerialSetBaud(
        !            90:     IN PVOID Context
        !            91:     )
        !            92: 
        !            93: /*++
        !            94: 
        !            95: Routine Description:
        !            96: 
        !            97:     This routine is used to set the buad rate of the device.
        !            98: 
        !            99: Arguments:
        !           100: 
        !           101:     Context - Pointer to a structure that contains a pointer to
        !           102:               the device extension and what should be the current
        !           103:               baud rate.
        !           104: 
        !           105: Return Value:
        !           106: 
        !           107:     This routine always returns FALSE.
        !           108: 
        !           109: --*/
        !           110: 
        !           111: {
        !           112: 
        !           113:     PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension;
        !           114:     USHORT Appropriate = (USHORT)(((PSERIAL_IOCTL_SYNC)Context)->Data);
        !           115: 
        !           116:     WRITE_DIVISOR_LATCH(
        !           117:         Extension->Controller,
        !           118:         Appropriate
        !           119:         );
        !           120: 
        !           121:     return FALSE;
        !           122: 
        !           123: }
        !           124: 
        !           125: BOOLEAN
        !           126: SerialSetLineControl(
        !           127:     IN PVOID Context
        !           128:     )
        !           129: 
        !           130: /*++
        !           131: 
        !           132: Routine Description:
        !           133: 
        !           134:     This routine is used to set the buad rate of the device.
        !           135: 
        !           136: Arguments:
        !           137: 
        !           138:     Context - Pointer to the device extension.
        !           139: 
        !           140: Return Value:
        !           141: 
        !           142:     This routine always returns FALSE.
        !           143: 
        !           144: --*/
        !           145: 
        !           146: {
        !           147: 
        !           148:     PSERIAL_DEVICE_EXTENSION Extension = Context;
        !           149: 
        !           150:     WRITE_LINE_CONTROL(
        !           151:         Extension->Controller,
        !           152:         Extension->LineControl
        !           153:         );
        !           154: 
        !           155:     return FALSE;
        !           156: 
        !           157: }
        !           158: 
        !           159: BOOLEAN
        !           160: SerialGetModemUpdate(
        !           161:     IN PVOID Context
        !           162:     )
        !           163: 
        !           164: /*++
        !           165: 
        !           166: Routine Description:
        !           167: 
        !           168:     This routine is simply used to call the interrupt level routine
        !           169:     that handles modem status update.
        !           170: 
        !           171: Arguments:
        !           172: 
        !           173:     Context - Pointer to a structure that contains a pointer to
        !           174:               the device extension and a pointer to a ulong.
        !           175: 
        !           176: Return Value:
        !           177: 
        !           178:     This routine always returns FALSE.
        !           179: 
        !           180: --*/
        !           181: 
        !           182: {
        !           183: 
        !           184:     PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension;
        !           185:     ULONG *Result = (ULONG *)(((PSERIAL_IOCTL_SYNC)Context)->Data);
        !           186: 
        !           187:     *Result = SerialHandleModemUpdate(
        !           188:                   Extension,
        !           189:                   FALSE
        !           190:                   );
        !           191: 
        !           192:     return FALSE;
        !           193: 
        !           194: }
        !           195: 
        !           196: BOOLEAN
        !           197: SerialGetCommStatus(
        !           198:     IN PVOID Context
        !           199:     )
        !           200: 
        !           201: /*++
        !           202: 
        !           203: Routine Description:
        !           204: 
        !           205:     This is used to get the current state of the serial driver.
        !           206: 
        !           207: Arguments:
        !           208: 
        !           209:     Context - Pointer to a structure that contains a pointer to
        !           210:               the device extension and a pointer to a serial status
        !           211:               record.
        !           212: 
        !           213: Return Value:
        !           214: 
        !           215:     This routine always returns FALSE.
        !           216: 
        !           217: --*/
        !           218: 
        !           219: {
        !           220: 
        !           221:     PSERIAL_DEVICE_EXTENSION Extension = ((PSERIAL_IOCTL_SYNC)Context)->Extension;
        !           222:     PSERIAL_STATUS Stat = ((PSERIAL_IOCTL_SYNC)Context)->Data;
        !           223: 
        !           224:     Stat->Errors = Extension->ErrorWord;
        !           225:     Extension->ErrorWord = 0;
        !           226: 
        !           227:     //
        !           228:     // BUG BUG We need to do something about eof (binary mode).
        !           229:     //
        !           230:     Stat->EofReceived = FALSE;
        !           231: 
        !           232:     Stat->AmountInInQueue = Extension->CharsInInterruptBuffer;
        !           233: 
        !           234:     Stat->AmountInOutQueue = Extension->TotalCharsQueued;
        !           235: 
        !           236:     if (Extension->WriteLength) {
        !           237: 
        !           238:         //
        !           239:         // By definition if we have a writelength the we have
        !           240:         // a current write irp.
        !           241:         //
        !           242: 
        !           243:         ASSERT(Extension->CurrentWriteIrp);
        !           244:         ASSERT(Stat->AmountInOutQueue >= Extension->WriteLength);
        !           245:         ASSERT((IoGetCurrentIrpStackLocation(Extension->CurrentWriteIrp)->
        !           246:                 Parameters.Write.Length) >=
        !           247:                 Extension->WriteLength);
        !           248: 
        !           249:         Stat->AmountInOutQueue -=
        !           250:             IoGetCurrentIrpStackLocation(Extension->CurrentWriteIrp)
        !           251:             ->Parameters.Write.Length - (Extension->WriteLength);
        !           252: 
        !           253:     }
        !           254: 
        !           255:     Stat->WaitForImmediate = Extension->TransmitImmediate;
        !           256: 
        !           257:     Stat->HoldReasons = 0;
        !           258:     if (Extension->TXHolding) {
        !           259: 
        !           260:         if (Extension->TXHolding & SERIAL_TX_CTS) {
        !           261: 
        !           262:             Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS;
        !           263: 
        !           264:         }
        !           265: 
        !           266:         if (Extension->TXHolding & SERIAL_TX_DSR) {
        !           267: 
        !           268:             Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DSR;
        !           269: 
        !           270:         }
        !           271: 
        !           272:         if (Extension->TXHolding & SERIAL_TX_DCD) {
        !           273: 
        !           274:             Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DCD;
        !           275: 
        !           276:         }
        !           277: 
        !           278:         if (Extension->TXHolding & SERIAL_TX_XOFF) {
        !           279: 
        !           280:             Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_XON;
        !           281: 
        !           282:         }
        !           283: 
        !           284:         if (Extension->TXHolding & SERIAL_TX_BREAK) {
        !           285: 
        !           286:             Stat->HoldReasons |= SERIAL_TX_WAITING_ON_BREAK;
        !           287: 
        !           288:         }
        !           289: 
        !           290:     }
        !           291: 
        !           292:     if (Extension->RXHolding & SERIAL_RX_DSR) {
        !           293: 
        !           294:         Stat->HoldReasons |= SERIAL_RX_WAITING_FOR_DSR;
        !           295: 
        !           296:     }
        !           297: 
        !           298:     if (Extension->RXHolding & SERIAL_RX_XOFF) {
        !           299: 
        !           300:         Stat->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;
        !           301: 
        !           302:     }
        !           303: 
        !           304:     return FALSE;
        !           305: 
        !           306: }
        !           307: 
        !           308: BOOLEAN
        !           309: SerialSetEscapeChar(
        !           310:     IN PVOID Context
        !           311:     )
        !           312: 
        !           313: /*++
        !           314: 
        !           315: Routine Description:
        !           316: 
        !           317:     This is used to set the character that will be used to escape
        !           318:     line status and modem status information when the application
        !           319:     has set up that line status and modem status should be passed
        !           320:     back in the data stream.
        !           321: 
        !           322: Arguments:
        !           323: 
        !           324:     Context - Pointer to the irp that is specify the escape character.
        !           325:               Implicitly - An escape character of 0 means no escaping
        !           326:               will occur.
        !           327: 
        !           328: Return Value:
        !           329: 
        !           330:     This routine always returns FALSE.
        !           331: 
        !           332: --*/
        !           333: 
        !           334: {
        !           335: 
        !           336:     PSERIAL_DEVICE_EXTENSION extension =
        !           337:         IoGetCurrentIrpStackLocation((PIRP)Context)
        !           338:             ->DeviceObject->DeviceExtension;
        !           339: 
        !           340:     extension->EscapeChar =
        !           341:         *(PUCHAR)((PIRP)Context)->AssociatedIrp.SystemBuffer;
        !           342: 
        !           343:     return FALSE;
        !           344: 
        !           345: }
        !           346: 
        !           347: NTSTATUS
        !           348: SerialIoControl(
        !           349:     IN PDEVICE_OBJECT DeviceObject,
        !           350:     IN PIRP Irp
        !           351:     )
        !           352: 
        !           353: /*++
        !           354: 
        !           355: Routine Description:
        !           356: 
        !           357:     This routine provides the initial processing for all of the
        !           358:     Ioctrls for the serial device.
        !           359: 
        !           360: Arguments:
        !           361: 
        !           362:     DeviceObject - Pointer to the device object for this device
        !           363: 
        !           364:     Irp - Pointer to the IRP for the current request
        !           365: 
        !           366: Return Value:
        !           367: 
        !           368:     The function value is the final status of the call
        !           369: 
        !           370: --*/
        !           371: 
        !           372: {
        !           373:     //
        !           374:     // The status that gets returned to the caller and
        !           375:     // set in the Irp.
        !           376:     //
        !           377:     NTSTATUS Status;
        !           378: 
        !           379:     //
        !           380:     // The current stack location.  This contains all of the
        !           381:     // information we need to process this particular request.
        !           382:     //
        !           383:     PIO_STACK_LOCATION IrpSp;
        !           384: 
        !           385:     //
        !           386:     // Just what it says.  This is the serial specific device
        !           387:     // extension of the device object create for the serial driver.
        !           388:     //
        !           389:     PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
        !           390: 
        !           391:     //
        !           392:     // A temporary to hold the old IRQL so that it can be
        !           393:     // restored once we complete/validate this request.
        !           394:     //
        !           395:     KIRQL OldIrql;
        !           396: 
        !           397:     SerialDump(
        !           398:         SERIRPPATH,
        !           399:         ("SERIAL: Dispatch entry for: %x\n",Irp)
        !           400:         );
        !           401:     if (SerialCompleteIfError(
        !           402:             DeviceObject,
        !           403:             Irp
        !           404:             ) != STATUS_SUCCESS) {
        !           405: 
        !           406:         return STATUS_CANCELLED;
        !           407: 
        !           408:     }
        !           409:     IrpSp = IoGetCurrentIrpStackLocation(Irp);
        !           410:     Irp->IoStatus.Information = 0L;
        !           411:     Status = STATUS_SUCCESS;
        !           412:     switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
        !           413: 
        !           414:         case IOCTL_SERIAL_SET_BAUD_RATE : {
        !           415: 
        !           416:             ULONG BaudRate;
        !           417:             //
        !           418:             // Will hold the value of the appropriate divisor for
        !           419:             // the requested baud rate.  If the baudrate is invalid
        !           420:             // (because the device won't support that baud rate) then
        !           421:             // this value is undefined.
        !           422:             //
        !           423:             // Note: in one sense the concept of a valid baud rate
        !           424:             // is cloudy.  We could allow the user to request any
        !           425:             // baud rate.  We could then calculate the divisor needed
        !           426:             // for that baud rate.  As long as the divisor wasn't less
        !           427:             // than one we would be "ok".  (The percentage difference
        !           428:             // between the "true" divisor and the "rounded" value given
        !           429:             // to the hardware might make it unusable, but... )  It would
        !           430:             // really be up to the user to "Know" whether the baud rate
        !           431:             // is suitable.  So much for theory, *We* only support a given
        !           432:             // set of baud rates.
        !           433:             //
        !           434:             SHORT AppropriateDivisor;
        !           435: 
        !           436:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !           437:                 sizeof(SERIAL_BAUD_RATE)) {
        !           438: 
        !           439:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           440:                 break;
        !           441: 
        !           442:             } else {
        !           443: 
        !           444:                 BaudRate = ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate;
        !           445: 
        !           446:             }
        !           447: 
        !           448:             //
        !           449:             // Get the baud rate from the irp.  We pass it
        !           450:             // to a routine which will set the correct divisor.
        !           451:             //
        !           452: 
        !           453:             Status = SerialGetDivisorFromBaud(
        !           454:                          Extension->ClockRate,
        !           455:                          BaudRate,
        !           456:                          &AppropriateDivisor
        !           457:                          );
        !           458: 
        !           459:             KeAcquireSpinLock(
        !           460:                 &Extension->ControlLock,
        !           461:                 &OldIrql
        !           462:                 );
        !           463: 
        !           464:             if (NT_SUCCESS(Status)) {
        !           465: 
        !           466:                 SERIAL_IOCTL_SYNC S;
        !           467: 
        !           468:                 Extension->CurrentBaud = BaudRate;
        !           469: 
        !           470:                 S.Extension = Extension;
        !           471:                 S.Data = (PVOID)AppropriateDivisor;
        !           472:                 KeSynchronizeExecution(
        !           473:                     Extension->Interrupt,
        !           474:                     SerialSetBaud,
        !           475:                     &S
        !           476:                     );
        !           477: 
        !           478:             }
        !           479: 
        !           480:             KeReleaseSpinLock(
        !           481:                 &Extension->ControlLock,
        !           482:                 OldIrql
        !           483:                 );
        !           484: 
        !           485:             break;
        !           486:         }
        !           487:         case IOCTL_SERIAL_GET_BAUD_RATE: {
        !           488: 
        !           489:             PSERIAL_BAUD_RATE Br = (PSERIAL_BAUD_RATE)Irp->AssociatedIrp.SystemBuffer;
        !           490:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !           491:                 sizeof(SERIAL_BAUD_RATE)) {
        !           492: 
        !           493:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           494:                 break;
        !           495: 
        !           496:             }
        !           497: 
        !           498:             KeAcquireSpinLock(
        !           499:                 &Extension->ControlLock,
        !           500:                 &OldIrql
        !           501:                 );
        !           502: 
        !           503:             Br->BaudRate = Extension->CurrentBaud;
        !           504: 
        !           505:             KeReleaseSpinLock(
        !           506:                 &Extension->ControlLock,
        !           507:                 OldIrql
        !           508:                 );
        !           509: 
        !           510:             Irp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);
        !           511: 
        !           512:             break;
        !           513: 
        !           514:         }
        !           515:         case IOCTL_SERIAL_SET_LINE_CONTROL: {
        !           516: 
        !           517:             //
        !           518:             // Points to the line control record in the Irp.
        !           519:             //
        !           520:             PSERIAL_LINE_CONTROL Lc =
        !           521:                 ((PSERIAL_LINE_CONTROL)(Irp->AssociatedIrp.SystemBuffer));
        !           522: 
        !           523:             UCHAR LData;
        !           524:             UCHAR LStop;
        !           525:             UCHAR LParity;
        !           526:             UCHAR Mask = 0xff;
        !           527: 
        !           528:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !           529:                 sizeof(SERIAL_LINE_CONTROL)) {
        !           530: 
        !           531:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           532:                 break;
        !           533: 
        !           534:             }
        !           535: 
        !           536:             switch (Lc->WordLength) {
        !           537:                 case 5: {
        !           538: 
        !           539:                     LData = SERIAL_5_DATA;
        !           540:                     Mask = 0x1f;
        !           541:                     break;
        !           542: 
        !           543:                 }
        !           544:                 case 6: {
        !           545: 
        !           546:                     LData = SERIAL_6_DATA;
        !           547:                     Mask = 0x3f;
        !           548:                     break;
        !           549: 
        !           550:                 }
        !           551:                 case 7: {
        !           552: 
        !           553:                     LData = SERIAL_7_DATA;
        !           554:                     Mask = 0x7f;
        !           555:                     break;
        !           556: 
        !           557:                 }
        !           558:                 case 8: {
        !           559: 
        !           560:                     LData = SERIAL_8_DATA;
        !           561:                     break;
        !           562: 
        !           563:                 }
        !           564:                 default: {
        !           565: 
        !           566:                     Status = STATUS_INVALID_PARAMETER;
        !           567:                     goto DoneWithIoctl;
        !           568: 
        !           569:                 }
        !           570: 
        !           571:             }
        !           572: 
        !           573:             switch (Lc->Parity) {
        !           574: 
        !           575:                 case NO_PARITY: {
        !           576: 
        !           577:                     LParity = SERIAL_NONE_PARITY;
        !           578:                     break;
        !           579: 
        !           580:                 }
        !           581:                 case EVEN_PARITY: {
        !           582: 
        !           583:                     LParity = SERIAL_EVEN_PARITY;
        !           584:                     break;
        !           585: 
        !           586:                 }
        !           587:                 case ODD_PARITY: {
        !           588: 
        !           589:                     LParity = SERIAL_ODD_PARITY;
        !           590:                     break;
        !           591: 
        !           592:                 }
        !           593:                 case SPACE_PARITY: {
        !           594: 
        !           595:                     LParity = SERIAL_SPACE_PARITY;
        !           596:                     break;
        !           597: 
        !           598:                 }
        !           599:                 case MARK_PARITY: {
        !           600: 
        !           601:                     LParity = SERIAL_MARK_PARITY;
        !           602:                     break;
        !           603: 
        !           604:                 }
        !           605:                 default: {
        !           606: 
        !           607:                     Status = STATUS_INVALID_PARAMETER;
        !           608:                     goto DoneWithIoctl;
        !           609:                     break;
        !           610:                 }
        !           611: 
        !           612:             }
        !           613: 
        !           614:             switch (Lc->StopBits) {
        !           615: 
        !           616:                 case STOP_BIT_1: {
        !           617: 
        !           618:                     LStop = SERIAL_1_STOP;
        !           619:                     break;
        !           620:                 }
        !           621:                 case STOP_BITS_1_5: {
        !           622: 
        !           623:                     if (LData != SERIAL_5_DATA) {
        !           624: 
        !           625:                         Status = STATUS_INVALID_PARAMETER;
        !           626:                         goto DoneWithIoctl;
        !           627:                     }
        !           628:                     LStop = SERIAL_1_5_STOP;
        !           629:                     break;
        !           630: 
        !           631:                 }
        !           632:                 case STOP_BITS_2: {
        !           633: 
        !           634:                     if (LData == SERIAL_5_DATA) {
        !           635: 
        !           636:                         Status = STATUS_INVALID_PARAMETER;
        !           637:                         goto DoneWithIoctl;
        !           638:                     }
        !           639:                     LStop = SERIAL_2_STOP;
        !           640:                     break;
        !           641: 
        !           642:                 }
        !           643:                 default: {
        !           644: 
        !           645:                     Status = STATUS_INVALID_PARAMETER;
        !           646:                     goto DoneWithIoctl;
        !           647:                 }
        !           648: 
        !           649:             }
        !           650: 
        !           651:             KeAcquireSpinLock(
        !           652:                 &Extension->ControlLock,
        !           653:                 &OldIrql
        !           654:                 );
        !           655: 
        !           656:             Extension->LineControl =
        !           657:                 (UCHAR)((Extension->LineControl & SERIAL_LCR_BREAK) |
        !           658:                         (LData | LParity | LStop));
        !           659:             Extension->ValidDataMask = Mask;
        !           660: 
        !           661:             KeSynchronizeExecution(
        !           662:                 Extension->Interrupt,
        !           663:                 SerialSetLineControl,
        !           664:                 Extension
        !           665:                 );
        !           666: 
        !           667:             KeReleaseSpinLock(
        !           668:                 &Extension->ControlLock,
        !           669:                 OldIrql
        !           670:                 );
        !           671: 
        !           672:             break;
        !           673:         }
        !           674:         case IOCTL_SERIAL_GET_LINE_CONTROL: {
        !           675: 
        !           676:             PSERIAL_LINE_CONTROL Lc = (PSERIAL_LINE_CONTROL)Irp->AssociatedIrp.SystemBuffer;
        !           677: 
        !           678:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !           679:                 sizeof(SERIAL_LINE_CONTROL)) {
        !           680: 
        !           681:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           682:                 break;
        !           683: 
        !           684:             }
        !           685: 
        !           686:             KeAcquireSpinLock(
        !           687:                 &Extension->ControlLock,
        !           688:                 &OldIrql
        !           689:                 );
        !           690: 
        !           691:             if ((Extension->LineControl & SERIAL_DATA_MASK) == SERIAL_5_DATA) {
        !           692:                 Lc->WordLength = 5;
        !           693:             } else if ((Extension->LineControl & SERIAL_DATA_MASK)
        !           694:                         == SERIAL_6_DATA) {
        !           695:                 Lc->WordLength = 6;
        !           696:             } else if ((Extension->LineControl & SERIAL_DATA_MASK)
        !           697:                         == SERIAL_7_DATA) {
        !           698:                 Lc->WordLength = 7;
        !           699:             } else if ((Extension->LineControl & SERIAL_DATA_MASK)
        !           700:                         == SERIAL_8_DATA) {
        !           701:                 Lc->WordLength = 8;
        !           702:             }
        !           703: 
        !           704:             if ((Extension->LineControl & SERIAL_PARITY_MASK)
        !           705:                     == SERIAL_NONE_PARITY) {
        !           706:                 Lc->Parity = NO_PARITY;
        !           707:             } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
        !           708:                     == SERIAL_ODD_PARITY) {
        !           709:                 Lc->Parity = ODD_PARITY;
        !           710:             } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
        !           711:                     == SERIAL_EVEN_PARITY) {
        !           712:                 Lc->Parity = EVEN_PARITY;
        !           713:             } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
        !           714:                     == SERIAL_MARK_PARITY) {
        !           715:                 Lc->Parity = MARK_PARITY;
        !           716:             } else if ((Extension->LineControl & SERIAL_PARITY_MASK)
        !           717:                     == SERIAL_SPACE_PARITY) {
        !           718:                 Lc->Parity = SPACE_PARITY;
        !           719:             }
        !           720: 
        !           721:             if (Extension->LineControl & SERIAL_2_STOP) {
        !           722:                 if (Lc->WordLength == 5) {
        !           723:                     Lc->StopBits = STOP_BITS_1_5;
        !           724:                 } else {
        !           725:                     Lc->StopBits = STOP_BITS_2;
        !           726:                 }
        !           727:             } else {
        !           728:                 Lc->StopBits = STOP_BIT_1;
        !           729:             }
        !           730: 
        !           731:             Irp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);
        !           732: 
        !           733:             KeReleaseSpinLock(
        !           734:                 &Extension->ControlLock,
        !           735:                 OldIrql
        !           736:                 );
        !           737: 
        !           738:             break;
        !           739:         }
        !           740:         case IOCTL_SERIAL_SET_TIMEOUTS: {
        !           741: 
        !           742:             PSERIAL_TIMEOUTS NewTimeouts =
        !           743:                 ((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer));
        !           744: 
        !           745: 
        !           746:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !           747:                 sizeof(SERIAL_TIMEOUTS)) {
        !           748: 
        !           749:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           750:                 break;
        !           751: 
        !           752:             }
        !           753: 
        !           754:             if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) &&
        !           755:                 (NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
        !           756:                 (NewTimeouts->ReadTotalTimeoutConstant == MAXULONG)) {
        !           757: 
        !           758:                 Status = STATUS_INVALID_PARAMETER;
        !           759:                 break;
        !           760: 
        !           761:             }
        !           762: 
        !           763:             KeAcquireSpinLock(
        !           764:                 &Extension->ControlLock,
        !           765:                 &OldIrql
        !           766:                 );
        !           767: 
        !           768:             Extension->Timeouts.ReadIntervalTimeout =
        !           769:                 NewTimeouts->ReadIntervalTimeout;
        !           770: 
        !           771:             Extension->Timeouts.ReadTotalTimeoutMultiplier =
        !           772:                 NewTimeouts->ReadTotalTimeoutMultiplier;
        !           773: 
        !           774:             Extension->Timeouts.ReadTotalTimeoutConstant =
        !           775:                 NewTimeouts->ReadTotalTimeoutConstant;
        !           776: 
        !           777:             Extension->Timeouts.WriteTotalTimeoutMultiplier =
        !           778:                 NewTimeouts->WriteTotalTimeoutMultiplier;
        !           779: 
        !           780:             Extension->Timeouts.WriteTotalTimeoutConstant =
        !           781:                 NewTimeouts->WriteTotalTimeoutConstant;
        !           782: 
        !           783:             KeReleaseSpinLock(
        !           784:                 &Extension->ControlLock,
        !           785:                 OldIrql
        !           786:                 );
        !           787: 
        !           788:             break;
        !           789:         }
        !           790:         case IOCTL_SERIAL_GET_TIMEOUTS: {
        !           791: 
        !           792:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !           793:                 sizeof(SERIAL_TIMEOUTS)) {
        !           794: 
        !           795:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           796:                 break;
        !           797: 
        !           798:             }
        !           799: 
        !           800:             KeAcquireSpinLock(
        !           801:                 &Extension->ControlLock,
        !           802:                 &OldIrql
        !           803:                 );
        !           804: 
        !           805:             *((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) = Extension->Timeouts;
        !           806:             Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
        !           807: 
        !           808:             KeReleaseSpinLock(
        !           809:                 &Extension->ControlLock,
        !           810:                 OldIrql
        !           811:                 );
        !           812: 
        !           813:             break;
        !           814:         }
        !           815:         case IOCTL_SERIAL_SET_CHARS: {
        !           816: 
        !           817:             SERIAL_IOCTL_SYNC S;
        !           818:             PSERIAL_CHARS NewChars =
        !           819:                 ((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
        !           820: 
        !           821: 
        !           822:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !           823:                 sizeof(SERIAL_CHARS)) {
        !           824: 
        !           825:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           826:                 break;
        !           827: 
        !           828:             }
        !           829: 
        !           830:             //
        !           831:             // The only thing that can be wrong with the chars
        !           832:             // is that the xon and xoff characters are the
        !           833:             // same.
        !           834:             //
        !           835: 
        !           836:             if (NewChars->XonChar == NewChars->XoffChar) {
        !           837: 
        !           838:                 Status = STATUS_INVALID_PARAMETER;
        !           839:                 break;
        !           840: 
        !           841:             }
        !           842: 
        !           843:             //
        !           844:             // We acquire the control lock so that only
        !           845:             // one request can GET or SET the characters
        !           846:             // at a time.  The sets could be synchronized
        !           847:             // by the interrupt spinlock, but that wouldn't
        !           848:             // prevent multiple gets at the same time.
        !           849:             //
        !           850: 
        !           851:             S.Extension = Extension;
        !           852:             S.Data = NewChars;
        !           853: 
        !           854:             KeAcquireSpinLock(
        !           855:                 &Extension->ControlLock,
        !           856:                 &OldIrql
        !           857:                 );
        !           858: 
        !           859:             //
        !           860:             // Under the protection of the lock, make sure that
        !           861:             // the xon and xoff characters aren't the same as
        !           862:             // the escape character.
        !           863:             //
        !           864: 
        !           865:             if (Extension->EscapeChar) {
        !           866: 
        !           867:                 if ((Extension->EscapeChar == NewChars->XonChar) ||
        !           868:                     (Extension->EscapeChar == NewChars->XoffChar)) {
        !           869: 
        !           870:                     Status = STATUS_INVALID_PARAMETER;
        !           871:                     KeReleaseSpinLock(
        !           872:                         &Extension->ControlLock,
        !           873:                         OldIrql
        !           874:                         );
        !           875:                     break;
        !           876: 
        !           877:                 }
        !           878: 
        !           879:             }
        !           880: 
        !           881:             KeSynchronizeExecution(
        !           882:                 Extension->Interrupt,
        !           883:                 SerialSetChars,
        !           884:                 &S
        !           885:                 );
        !           886: 
        !           887:             KeReleaseSpinLock(
        !           888:                 &Extension->ControlLock,
        !           889:                 OldIrql
        !           890:                 );
        !           891: 
        !           892:             break;
        !           893: 
        !           894:         }
        !           895:         case IOCTL_SERIAL_GET_CHARS: {
        !           896: 
        !           897:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !           898:                 sizeof(SERIAL_CHARS)) {
        !           899: 
        !           900:                 Status = STATUS_BUFFER_TOO_SMALL;
        !           901:                 break;
        !           902: 
        !           903:             }
        !           904: 
        !           905:             KeAcquireSpinLock(
        !           906:                 &Extension->ControlLock,
        !           907:                 &OldIrql
        !           908:                 );
        !           909: 
        !           910:             *((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer) = Extension->SpecialChars;
        !           911:             Irp->IoStatus.Information = sizeof(SERIAL_CHARS);
        !           912: 
        !           913:             KeReleaseSpinLock(
        !           914:                 &Extension->ControlLock,
        !           915:                 OldIrql
        !           916:                 );
        !           917: 
        !           918:             break;
        !           919:         }
        !           920:         case IOCTL_SERIAL_SET_DTR:
        !           921:         case IOCTL_SERIAL_CLR_DTR: {
        !           922: 
        !           923:             //
        !           924:             // We acquire the lock so that we can check whether
        !           925:             // automatic dtr flow control is enabled.  If it is
        !           926:             // then we return an error since the app is not allowed
        !           927:             // to touch this if it is automatic.
        !           928:             //
        !           929: 
        !           930:             KeAcquireSpinLock(
        !           931:                 &Extension->ControlLock,
        !           932:                 &OldIrql
        !           933:                 );
        !           934: 
        !           935:             if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK)
        !           936:                 == SERIAL_DTR_HANDSHAKE) {
        !           937: 
        !           938:                 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
        !           939: 
        !           940:             } else {
        !           941: 
        !           942:                 KeSynchronizeExecution(
        !           943:                     Extension->Interrupt,
        !           944:                     ((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
        !           945:                      IOCTL_SERIAL_SET_DTR)?
        !           946:                      (SerialSetDTR):(SerialClrDTR)),
        !           947:                     Extension
        !           948:                     );
        !           949: 
        !           950:             }
        !           951: 
        !           952:             KeReleaseSpinLock(
        !           953:                 &Extension->ControlLock,
        !           954:                 OldIrql
        !           955:                 );
        !           956: 
        !           957:             break;
        !           958:         }
        !           959:         case IOCTL_SERIAL_RESET_DEVICE: {
        !           960: 
        !           961:             break;
        !           962:         }
        !           963:         case IOCTL_SERIAL_SET_RTS:
        !           964:         case IOCTL_SERIAL_CLR_RTS: {
        !           965:             //
        !           966:             // We acquire the lock so that we can check whether
        !           967:             // automatic rts flow control or transmit toggleing
        !           968:             // is enabled.  If it is then we return an error since
        !           969:             // the app is not allowed to touch this if it is automatic
        !           970:             // or toggling.
        !           971:             //
        !           972: 
        !           973:             KeAcquireSpinLock(
        !           974:                 &Extension->ControlLock,
        !           975:                 &OldIrql
        !           976:                 );
        !           977: 
        !           978:             if (((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
        !           979:                  == SERIAL_RTS_HANDSHAKE) ||
        !           980:                 ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK)
        !           981:                  == SERIAL_TRANSMIT_TOGGLE)) {
        !           982: 
        !           983:                 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
        !           984: 
        !           985:             } else {
        !           986: 
        !           987:                 KeSynchronizeExecution(
        !           988:                     Extension->Interrupt,
        !           989:                     ((IrpSp->Parameters.DeviceIoControl.IoControlCode ==
        !           990:                      IOCTL_SERIAL_SET_RTS)?
        !           991:                      (SerialSetRTS):(SerialClrRTS)),
        !           992:                     Extension
        !           993:                     );
        !           994: 
        !           995:             }
        !           996: 
        !           997:             KeReleaseSpinLock(
        !           998:                 &Extension->ControlLock,
        !           999:                 OldIrql
        !          1000:                 );
        !          1001: 
        !          1002:             break;
        !          1003: 
        !          1004:         }
        !          1005:         case IOCTL_SERIAL_SET_XOFF: {
        !          1006: 
        !          1007:             KeSynchronizeExecution(
        !          1008:                 Extension->Interrupt,
        !          1009:                 SerialPretendXoff,
        !          1010:                 Extension
        !          1011:                 );
        !          1012: 
        !          1013:             break;
        !          1014: 
        !          1015:         }
        !          1016:         case IOCTL_SERIAL_SET_XON: {
        !          1017: 
        !          1018:             KeSynchronizeExecution(
        !          1019:                 Extension->Interrupt,
        !          1020:                 SerialPretendXon,
        !          1021:                 Extension
        !          1022:                 );
        !          1023: 
        !          1024:             break;
        !          1025: 
        !          1026:         }
        !          1027:         case IOCTL_SERIAL_SET_BREAK_ON: {
        !          1028: 
        !          1029:             KeSynchronizeExecution(
        !          1030:                 Extension->Interrupt,
        !          1031:                 SerialTurnOnBreak,
        !          1032:                 Extension
        !          1033:                 );
        !          1034: 
        !          1035:             break;
        !          1036:         }
        !          1037:         case IOCTL_SERIAL_SET_BREAK_OFF: {
        !          1038: 
        !          1039:             KeSynchronizeExecution(
        !          1040:                 Extension->Interrupt,
        !          1041:                 SerialTurnOffBreak,
        !          1042:                 Extension
        !          1043:                 );
        !          1044: 
        !          1045:             break;
        !          1046:         }
        !          1047:         case IOCTL_SERIAL_SET_QUEUE_SIZE: {
        !          1048: 
        !          1049:             //
        !          1050:             // Type ahead buffer is fixed, so we just validate
        !          1051:             // the the users request is not bigger that our
        !          1052:             // own internal buffer size.
        !          1053:             //
        !          1054: 
        !          1055:             PSERIAL_QUEUE_SIZE Rs =
        !          1056:                 ((PSERIAL_QUEUE_SIZE)(Irp->AssociatedIrp.SystemBuffer));
        !          1057: 
        !          1058:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !          1059:                 sizeof(SERIAL_QUEUE_SIZE)) {
        !          1060: 
        !          1061:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1062:                 break;
        !          1063: 
        !          1064:             }
        !          1065: 
        !          1066:             //
        !          1067:             // We have to allocate the memory for the new
        !          1068:             // buffer while we're still in the context of the
        !          1069:             // caller.  We don't even try to protect this
        !          1070:             // with a lock because the value could be stale
        !          1071:             // as soon as we release the lock - The only time
        !          1072:             // we will know for sure is when we actually try
        !          1073:             // to do the resize.
        !          1074:             //
        !          1075: 
        !          1076:             if (Rs->InSize <= Extension->BufferSize) {
        !          1077: 
        !          1078:                 Status = STATUS_SUCCESS;
        !          1079:                 break;
        !          1080: 
        !          1081:             }
        !          1082: 
        !          1083:             try {
        !          1084: 
        !          1085:                 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer =
        !          1086:                     ExAllocatePoolWithQuota(
        !          1087:                         NonPagedPool,
        !          1088:                         Rs->InSize
        !          1089:                         );
        !          1090: 
        !          1091:             } except (EXCEPTION_EXECUTE_HANDLER) {
        !          1092: 
        !          1093:                 IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
        !          1094:                 Status = GetExceptionCode();
        !          1095: 
        !          1096:             }
        !          1097: 
        !          1098:             if (!IrpSp->Parameters.DeviceIoControl.Type3InputBuffer) {
        !          1099: 
        !          1100:                 break;
        !          1101: 
        !          1102:             }
        !          1103: 
        !          1104:             //
        !          1105:             // Well the data passed was big enough.  Do the request.
        !          1106:             //
        !          1107:             // There are two reason we place it in the read queue:
        !          1108:             //
        !          1109:             // 1) We want to serialize these resize requests so that
        !          1110:             //    they don't contend with each other.
        !          1111:             //
        !          1112:             // 2) We want to serialize these requests with reads since
        !          1113:             //    we don't want reads and resizes contending over the
        !          1114:             //    read buffer.
        !          1115:             //
        !          1116: 
        !          1117:             return SerialStartOrQueue(
        !          1118:                        Extension,
        !          1119:                        Irp,
        !          1120:                        &Extension->ReadQueue,
        !          1121:                        &Extension->CurrentReadIrp,
        !          1122:                        SerialStartRead
        !          1123:                        );
        !          1124: 
        !          1125:             break;
        !          1126: 
        !          1127:         }
        !          1128:         case IOCTL_SERIAL_GET_WAIT_MASK: {
        !          1129: 
        !          1130:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !          1131:                 sizeof(ULONG)) {
        !          1132: 
        !          1133:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1134:                 break;
        !          1135: 
        !          1136:             }
        !          1137: 
        !          1138:             //
        !          1139:             // Simple scalar read.  No reason to acquire a lock.
        !          1140:             //
        !          1141: 
        !          1142:             Irp->IoStatus.Information = sizeof(ULONG);
        !          1143: 
        !          1144:             *((ULONG *)Irp->AssociatedIrp.SystemBuffer) = Extension->IsrWaitMask;
        !          1145: 
        !          1146:             break;
        !          1147: 
        !          1148:         }
        !          1149:         case IOCTL_SERIAL_SET_WAIT_MASK: {
        !          1150: 
        !          1151:             ULONG NewMask;
        !          1152: 
        !          1153:             SerialDump(
        !          1154:                 SERDIAG3 | SERIRPPATH,
        !          1155:                 ("SERIAL: In Ioctl processing for set mask\n")
        !          1156:                 );
        !          1157:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !          1158:                 sizeof(ULONG)) {
        !          1159: 
        !          1160:                 SerialDump(
        !          1161:                     SERDIAG3,
        !          1162:                     ("SERIAL: Invalid size fo the buffer %d\n",
        !          1163:                      IrpSp->Parameters.DeviceIoControl.InputBufferLength)
        !          1164:                     );
        !          1165:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1166:                 break;
        !          1167: 
        !          1168:             } else {
        !          1169: 
        !          1170:                 NewMask = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
        !          1171: 
        !          1172:             }
        !          1173: 
        !          1174:             //
        !          1175:             // Make sure that the mask only contains valid
        !          1176:             // waitable events.
        !          1177:             //
        !          1178: 
        !          1179:             if (NewMask & ~(SERIAL_EV_RXCHAR   |
        !          1180:                             SERIAL_EV_RXFLAG   |
        !          1181:                             SERIAL_EV_TXEMPTY  |
        !          1182:                             SERIAL_EV_CTS      |
        !          1183:                             SERIAL_EV_DSR      |
        !          1184:                             SERIAL_EV_RLSD     |
        !          1185:                             SERIAL_EV_BREAK    |
        !          1186:                             SERIAL_EV_ERR      |
        !          1187:                             SERIAL_EV_RING     |
        !          1188:                             SERIAL_EV_PERR     |
        !          1189:                             SERIAL_EV_RX80FULL |
        !          1190:                             SERIAL_EV_EVENT1   |
        !          1191:                             SERIAL_EV_EVENT2)) {
        !          1192: 
        !          1193:                 SerialDump(
        !          1194:                     SERDIAG3,
        !          1195:                     ("SERIAL: Unknown mask %x\n",NewMask)
        !          1196:                     );
        !          1197:                 Status = STATUS_INVALID_PARAMETER;
        !          1198:                 break;
        !          1199: 
        !          1200:             }
        !          1201: 
        !          1202:             //
        !          1203:             // Either start this irp or put it on the
        !          1204:             // queue.
        !          1205:             //
        !          1206: 
        !          1207:             SerialDump(
        !          1208:                 SERDIAG3 | SERIRPPATH,
        !          1209:                 ("SERIAL: Starting or queuing set mask irp %x\n",Irp)
        !          1210:                 );
        !          1211:             return SerialStartOrQueue(
        !          1212:                        Extension,
        !          1213:                        Irp,
        !          1214:                        &Extension->MaskQueue,
        !          1215:                        &Extension->CurrentMaskIrp,
        !          1216:                        SerialStartMask
        !          1217:                        );
        !          1218: 
        !          1219:         }
        !          1220:         case IOCTL_SERIAL_WAIT_ON_MASK: {
        !          1221: 
        !          1222:             SerialDump(
        !          1223:                 SERDIAG3 | SERIRPPATH,
        !          1224:                 ("SERIAL: In Ioctl processing for wait mask\n")
        !          1225:                 );
        !          1226:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !          1227:                 sizeof(ULONG)) {
        !          1228: 
        !          1229:                 SerialDump(
        !          1230:                     SERDIAG3,
        !          1231:                     ("SERIAL: Invalid size fo the buffer %d\n",
        !          1232:                      IrpSp->Parameters.DeviceIoControl.InputBufferLength)
        !          1233:                     );
        !          1234:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1235:                 break;
        !          1236: 
        !          1237:             }
        !          1238: 
        !          1239:             //
        !          1240:             // Either start this irp or put it on the
        !          1241:             // queue.
        !          1242:             //
        !          1243: 
        !          1244:             SerialDump(
        !          1245:                 SERDIAG3 | SERIRPPATH,
        !          1246:                 ("SERIAL: Starting or queuing wait mask irp %x\n",Irp)
        !          1247:                 );
        !          1248:             return SerialStartOrQueue(
        !          1249:                        Extension,
        !          1250:                        Irp,
        !          1251:                        &Extension->MaskQueue,
        !          1252:                        &Extension->CurrentMaskIrp,
        !          1253:                        SerialStartMask
        !          1254:                        );
        !          1255: 
        !          1256:         }
        !          1257:         case IOCTL_SERIAL_IMMEDIATE_CHAR: {
        !          1258: 
        !          1259:             KIRQL OldIrql;
        !          1260:             BOOLEAN FailRequest;
        !          1261: 
        !          1262:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !          1263:                 sizeof(UCHAR)) {
        !          1264: 
        !          1265:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1266:                 break;
        !          1267: 
        !          1268:             }
        !          1269: 
        !          1270:             IoAcquireCancelSpinLock(&OldIrql);
        !          1271:             if (Extension->CurrentImmediateIrp) {
        !          1272: 
        !          1273:                 FailRequest = TRUE;
        !          1274:                 Status = STATUS_INVALID_PARAMETER;
        !          1275:                 Irp->IoStatus.Status = Status;
        !          1276:                 IoReleaseCancelSpinLock(OldIrql);
        !          1277: 
        !          1278:             } else {
        !          1279: 
        !          1280:                 //
        !          1281:                 // We can queue the char.  We need to set
        !          1282:                 // a cancel routine because flow control could
        !          1283:                 // keep the char from transmitting.  Make sure
        !          1284:                 // that the irp hasn't already been canceled.
        !          1285:                 //
        !          1286: 
        !          1287:                 if (Irp->Cancel) {
        !          1288: 
        !          1289:                     IoReleaseCancelSpinLock(OldIrql);
        !          1290:                     Irp->IoStatus.Status = STATUS_CANCELLED;
        !          1291:                     Status = STATUS_CANCELLED;
        !          1292: 
        !          1293:                 } else {
        !          1294: 
        !          1295:                     Extension->CurrentImmediateIrp = Irp;
        !          1296:                     Extension->TotalCharsQueued++;
        !          1297:                     IoReleaseCancelSpinLock(OldIrql);
        !          1298:                     SerialStartImmediate(Extension);
        !          1299: 
        !          1300:                     return STATUS_PENDING;
        !          1301: 
        !          1302:                 }
        !          1303: 
        !          1304:             }
        !          1305: 
        !          1306:         }
        !          1307:         case IOCTL_SERIAL_PURGE: {
        !          1308: 
        !          1309:             ULONG Mask;
        !          1310: 
        !          1311:             //
        !          1312:             // Check to make sure that the mask only has
        !          1313:             // 0 or the other appropriate values.
        !          1314:             //
        !          1315: 
        !          1316:             Mask = *((ULONG *)(Irp->AssociatedIrp.SystemBuffer));
        !          1317: 
        !          1318:             if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT |
        !          1319:                                       SERIAL_PURGE_RXABORT |
        !          1320:                                       SERIAL_PURGE_TXCLEAR |
        !          1321:                                       SERIAL_PURGE_RXCLEAR
        !          1322:                                      )
        !          1323:                                    )
        !          1324:                            )) {
        !          1325: 
        !          1326:                 Status = STATUS_INVALID_PARAMETER;
        !          1327:                 break;
        !          1328: 
        !          1329:             }
        !          1330: 
        !          1331:             //
        !          1332:             // Either start this irp or put it on the
        !          1333:             // queue.
        !          1334:             //
        !          1335: 
        !          1336:             return SerialStartOrQueue(
        !          1337:                        Extension,
        !          1338:                        Irp,
        !          1339:                        &Extension->PurgeQueue,
        !          1340:                        &Extension->CurrentPurgeIrp,
        !          1341:                        SerialStartPurge
        !          1342:                        );
        !          1343: 
        !          1344:         }
        !          1345:         case IOCTL_SERIAL_GET_HANDFLOW: {
        !          1346: 
        !          1347:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !          1348:                 sizeof(SERIAL_HANDFLOW)) {
        !          1349: 
        !          1350:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1351:                 break;
        !          1352: 
        !          1353:             }
        !          1354: 
        !          1355:             Irp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
        !          1356: 
        !          1357:             KeAcquireSpinLock(
        !          1358:                 &Extension->ControlLock,
        !          1359:                 &OldIrql
        !          1360:                 );
        !          1361: 
        !          1362:             *((PSERIAL_HANDFLOW)Irp->AssociatedIrp.SystemBuffer) =
        !          1363:                 Extension->HandFlow;
        !          1364: 
        !          1365:             KeReleaseSpinLock(
        !          1366:                 &Extension->ControlLock,
        !          1367:                 OldIrql
        !          1368:                 );
        !          1369: 
        !          1370:             break;
        !          1371: 
        !          1372:         }
        !          1373:         case IOCTL_SERIAL_SET_HANDFLOW: {
        !          1374: 
        !          1375:             SERIAL_IOCTL_SYNC S;
        !          1376:             PSERIAL_HANDFLOW HandFlow = Irp->AssociatedIrp.SystemBuffer;
        !          1377: 
        !          1378:             //
        !          1379:             // Make sure that the hand shake and control is the
        !          1380:             // right size.
        !          1381:             //
        !          1382: 
        !          1383:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !          1384:                 sizeof(SERIAL_HANDFLOW)) {
        !          1385: 
        !          1386:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1387:                 break;
        !          1388: 
        !          1389:             }
        !          1390: 
        !          1391:             //
        !          1392:             // Make sure that there are no invalid bits set in
        !          1393:             // the control and handshake.
        !          1394:             //
        !          1395: 
        !          1396:             if (HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID) {
        !          1397: 
        !          1398:                 Status = STATUS_INVALID_PARAMETER;
        !          1399:                 break;
        !          1400: 
        !          1401:             }
        !          1402: 
        !          1403:             if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID) {
        !          1404: 
        !          1405:                 Status = STATUS_INVALID_PARAMETER;
        !          1406:                 break;
        !          1407: 
        !          1408:             }
        !          1409: 
        !          1410:             //
        !          1411:             // Make sure that the app hasn't set an invlid DTR mode.
        !          1412:             //
        !          1413: 
        !          1414:             if ((HandFlow->ControlHandShake & SERIAL_DTR_MASK) ==
        !          1415:                 SERIAL_DTR_MASK) {
        !          1416: 
        !          1417:                 Status = STATUS_INVALID_PARAMETER;
        !          1418:                 break;
        !          1419: 
        !          1420:             }
        !          1421: 
        !          1422:             //
        !          1423:             // Make sure that haven't set totally invalid xon/xoff
        !          1424:             // limits.
        !          1425:             //
        !          1426: 
        !          1427:             if ((HandFlow->XonLimit < 0) ||
        !          1428:                 ((ULONG)HandFlow->XonLimit > Extension->BufferSize)) {
        !          1429: 
        !          1430:                 Status = STATUS_INVALID_PARAMETER;
        !          1431:                 break;
        !          1432: 
        !          1433:             }
        !          1434: 
        !          1435:             if ((HandFlow->XoffLimit < 0) ||
        !          1436:                 ((ULONG)HandFlow->XoffLimit > Extension->BufferSize)) {
        !          1437: 
        !          1438:                 Status = STATUS_INVALID_PARAMETER;
        !          1439:                 break;
        !          1440: 
        !          1441:             }
        !          1442: 
        !          1443:             S.Extension = Extension;
        !          1444:             S.Data = HandFlow;
        !          1445: 
        !          1446:             KeAcquireSpinLock(
        !          1447:                 &Extension->ControlLock,
        !          1448:                 &OldIrql
        !          1449:                 );
        !          1450: 
        !          1451:             //
        !          1452:             // Under the protection of the lock, make sure that
        !          1453:             // we aren't turning on error replacement when we
        !          1454:             // are doing line status/modem status insertion.
        !          1455:             //
        !          1456: 
        !          1457:             if (Extension->EscapeChar) {
        !          1458: 
        !          1459:                 if (HandFlow->FlowReplace & SERIAL_ERROR_CHAR) {
        !          1460: 
        !          1461:                     Status = STATUS_INVALID_PARAMETER;
        !          1462:                     KeReleaseSpinLock(
        !          1463:                         &Extension->ControlLock,
        !          1464:                         OldIrql
        !          1465:                         );
        !          1466:                     break;
        !          1467: 
        !          1468:                 }
        !          1469: 
        !          1470:             }
        !          1471: 
        !          1472:             KeSynchronizeExecution(
        !          1473:                 Extension->Interrupt,
        !          1474:                 SerialSetHandFlow,
        !          1475:                 &S
        !          1476:                 );
        !          1477: 
        !          1478:             KeReleaseSpinLock(
        !          1479:                 &Extension->ControlLock,
        !          1480:                 OldIrql
        !          1481:                 );
        !          1482: 
        !          1483:             break;
        !          1484: 
        !          1485:         }
        !          1486:         case IOCTL_SERIAL_GET_MODEMSTATUS: {
        !          1487: 
        !          1488:             SERIAL_IOCTL_SYNC S;
        !          1489: 
        !          1490:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !          1491:                 sizeof(ULONG)) {
        !          1492: 
        !          1493:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1494:                 break;
        !          1495: 
        !          1496:             }
        !          1497: 
        !          1498:             Irp->IoStatus.Information = sizeof(ULONG);
        !          1499: 
        !          1500:             S.Extension = Extension;
        !          1501:             S.Data = Irp->AssociatedIrp.SystemBuffer;
        !          1502: 
        !          1503:             KeAcquireSpinLock(
        !          1504:                 &Extension->ControlLock,
        !          1505:                 &OldIrql
        !          1506:                 );
        !          1507: 
        !          1508:             KeSynchronizeExecution(
        !          1509:                 Extension->Interrupt,
        !          1510:                 SerialGetModemUpdate,
        !          1511:                 &S
        !          1512:                 );
        !          1513: 
        !          1514:             KeReleaseSpinLock(
        !          1515:                 &Extension->ControlLock,
        !          1516:                 OldIrql
        !          1517:                 );
        !          1518: 
        !          1519:             break;
        !          1520: 
        !          1521:         }
        !          1522:         case IOCTL_SERIAL_GET_DTRRTS: {
        !          1523: 
        !          1524:             ULONG ModemControl;
        !          1525:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !          1526:                 sizeof(ULONG)) {
        !          1527: 
        !          1528:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1529:                 break;
        !          1530: 
        !          1531:             }
        !          1532: 
        !          1533:             Irp->IoStatus.Information = sizeof(ULONG);
        !          1534:             Irp->IoStatus.Status = STATUS_SUCCESS;
        !          1535: 
        !          1536:             //
        !          1537:             // Reading this hardware has no effect on the device.
        !          1538:             //
        !          1539: 
        !          1540:             ModemControl = READ_MODEM_CONTROL(Extension->Controller);
        !          1541: 
        !          1542:             ModemControl &= SERIAL_DTR_STATE | SERIAL_RTS_STATE;
        !          1543: 
        !          1544:             *(PULONG)Irp->AssociatedIrp.SystemBuffer = ModemControl;
        !          1545: 
        !          1546:             break;
        !          1547: 
        !          1548:         }
        !          1549:         case IOCTL_SERIAL_GET_COMMSTATUS: {
        !          1550: 
        !          1551:             SERIAL_IOCTL_SYNC S;
        !          1552: 
        !          1553:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !          1554:                 sizeof(SERIAL_STATUS)) {
        !          1555: 
        !          1556:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1557:                 break;
        !          1558: 
        !          1559:             }
        !          1560: 
        !          1561:             Irp->IoStatus.Information = sizeof(SERIAL_STATUS);
        !          1562: 
        !          1563:             S.Extension = Extension;
        !          1564:             S.Data =  Irp->AssociatedIrp.SystemBuffer;
        !          1565: 
        !          1566:             //
        !          1567:             // Acquire the cancel spin lock so nothing much
        !          1568:             // changes while were getting the state.
        !          1569:             //
        !          1570: 
        !          1571:             IoAcquireCancelSpinLock(&OldIrql);
        !          1572: 
        !          1573:             KeSynchronizeExecution(
        !          1574:                 Extension->Interrupt,
        !          1575:                 SerialGetCommStatus,
        !          1576:                 &S
        !          1577:                 );
        !          1578: 
        !          1579:             IoReleaseCancelSpinLock(OldIrql);
        !          1580: 
        !          1581:             break;
        !          1582: 
        !          1583:         }
        !          1584:         case IOCTL_SERIAL_GET_PROPERTIES: {
        !          1585: 
        !          1586: 
        !          1587:             if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
        !          1588:                 sizeof(SERIAL_COMMPROP)) {
        !          1589: 
        !          1590:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1591:                 break;
        !          1592: 
        !          1593:             }
        !          1594: 
        !          1595:             //
        !          1596:             // No synchronization is required since this information
        !          1597:             // is "static".
        !          1598:             //
        !          1599: 
        !          1600:             SerialGetProperties(
        !          1601:                 Extension,
        !          1602:                 Irp->AssociatedIrp.SystemBuffer
        !          1603:                 );
        !          1604: 
        !          1605:             Irp->IoStatus.Information = sizeof(SERIAL_COMMPROP);
        !          1606:             Irp->IoStatus.Status = STATUS_SUCCESS;
        !          1607: 
        !          1608:             break;
        !          1609:         }
        !          1610:         case IOCTL_SERIAL_XOFF_COUNTER: {
        !          1611: 
        !          1612:             PSERIAL_XOFF_COUNTER Xc = Irp->AssociatedIrp.SystemBuffer;
        !          1613: 
        !          1614:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !          1615:                 sizeof(SERIAL_XOFF_COUNTER)) {
        !          1616: 
        !          1617:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1618:                 break;
        !          1619: 
        !          1620:             }
        !          1621: 
        !          1622:             if (Xc->Counter <= 0) {
        !          1623: 
        !          1624:                 Status = STATUS_INVALID_PARAMETER;
        !          1625:                 break;
        !          1626: 
        !          1627:             }
        !          1628: 
        !          1629:             //
        !          1630:             // So far so good.  Put the irp onto the write queue.
        !          1631:             //
        !          1632: 
        !          1633:             return SerialStartOrQueue(
        !          1634:                        Extension,
        !          1635:                        Irp,
        !          1636:                        &Extension->WriteQueue,
        !          1637:                        &Extension->CurrentWriteIrp,
        !          1638:                        SerialStartWrite
        !          1639:                        );
        !          1640: 
        !          1641:         }
        !          1642:         case IOCTL_SERIAL_LSRMST_INSERT: {
        !          1643: 
        !          1644:             PUCHAR escapeChar = Irp->AssociatedIrp.SystemBuffer;
        !          1645: 
        !          1646:             //
        !          1647:             // Make sure we get a byte.
        !          1648:             //
        !          1649: 
        !          1650:             if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
        !          1651:                 sizeof(UCHAR)) {
        !          1652: 
        !          1653:                 Status = STATUS_BUFFER_TOO_SMALL;
        !          1654:                 break;
        !          1655: 
        !          1656:             }
        !          1657: 
        !          1658:             KeAcquireSpinLock(
        !          1659:                 &Extension->ControlLock,
        !          1660:                 &OldIrql
        !          1661:                 );
        !          1662: 
        !          1663:             if (*escapeChar) {
        !          1664: 
        !          1665:                 //
        !          1666:                 // We've got some escape work to do.  We will make sure that
        !          1667:                 // the character is not the same as the Xon or Xoff character,
        !          1668:                 // or that we are already doing error replacement.
        !          1669:                 //
        !          1670: 
        !          1671:                 if ((*escapeChar == Extension->SpecialChars.XoffChar) ||
        !          1672:                     (*escapeChar == Extension->SpecialChars.XonChar) ||
        !          1673:                     (Extension->HandFlow.FlowReplace & SERIAL_ERROR_CHAR)) {
        !          1674: 
        !          1675:                     Status = STATUS_INVALID_PARAMETER;
        !          1676: 
        !          1677:                     KeReleaseSpinLock(
        !          1678:                         &Extension->ControlLock,
        !          1679:                         OldIrql
        !          1680:                         );
        !          1681:                     break;
        !          1682: 
        !          1683:                 }
        !          1684: 
        !          1685:             }
        !          1686: 
        !          1687:             KeSynchronizeExecution(
        !          1688:                 Extension->Interrupt,
        !          1689:                 SerialSetEscapeChar,
        !          1690:                 Irp
        !          1691:                 );
        !          1692: 
        !          1693:             KeReleaseSpinLock(
        !          1694:                 &Extension->ControlLock,
        !          1695:                 OldIrql
        !          1696:                 );
        !          1697: 
        !          1698:             break;
        !          1699: 
        !          1700:         }
        !          1701:         default: {
        !          1702: 
        !          1703:             Status = STATUS_INVALID_PARAMETER;
        !          1704:             break;
        !          1705:         }
        !          1706:     }
        !          1707: 
        !          1708: DoneWithIoctl:;
        !          1709: 
        !          1710:     Irp->IoStatus.Status = Status;
        !          1711: 
        !          1712:     SerialDump(
        !          1713:         SERIRPPATH,
        !          1714:         ("SERIAL: Complete Irp: %x\n",Irp)
        !          1715:         );
        !          1716:     IoCompleteRequest(
        !          1717:         Irp,
        !          1718:         0
        !          1719:         );
        !          1720: 
        !          1721:     return Status;
        !          1722: 
        !          1723: }
        !          1724: 
        !          1725: VOID
        !          1726: SerialGetProperties(
        !          1727:     IN PSERIAL_DEVICE_EXTENSION Extension,
        !          1728:     IN PSERIAL_COMMPROP Properties
        !          1729:     )
        !          1730: 
        !          1731: /*++
        !          1732: 
        !          1733: Routine Description:
        !          1734: 
        !          1735:     This function returns the capabilities of this particular
        !          1736:     serial device.
        !          1737: 
        !          1738: Arguments:
        !          1739: 
        !          1740:     Extension - The serial device extension.
        !          1741: 
        !          1742:     Properties - The structure used to return the properties
        !          1743: 
        !          1744: Return Value:
        !          1745: 
        !          1746:     None.
        !          1747: 
        !          1748: --*/
        !          1749: 
        !          1750: {
        !          1751: 
        !          1752:     RtlZeroMemory(
        !          1753:         Properties,
        !          1754:         sizeof(SERIAL_COMMPROP)
        !          1755:         );
        !          1756: 
        !          1757:     Properties->PacketLength = sizeof(SERIAL_COMMPROP);
        !          1758:     Properties->PacketVersion = 2;
        !          1759:     Properties->ServiceMask = SERIAL_SP_SERIALCOMM;
        !          1760:     Properties->MaxTxQueue = 0;
        !          1761:     Properties->MaxRxQueue = 0;
        !          1762: 
        !          1763:     Properties->MaxBaud = SERIAL_BAUD_USER;
        !          1764:     Properties->SettableBaud = Extension->SupportedBauds;
        !          1765: 
        !          1766:     Properties->ProvSubType = SERIAL_SP_RS232;
        !          1767:     Properties->ProvCapabilities = SERIAL_PCF_DTRDSR |
        !          1768:                                    SERIAL_PCF_RTSCTS |
        !          1769:                                    SERIAL_PCF_CD     |
        !          1770:                                    SERIAL_PCF_PARITY_CHECK |
        !          1771:                                    SERIAL_PCF_XONXOFF |
        !          1772:                                    SERIAL_PCF_SETXCHAR |
        !          1773:                                    SERIAL_PCF_TOTALTIMEOUTS |
        !          1774:                                    SERIAL_PCF_INTTIMEOUTS;
        !          1775:     Properties->SettableParams = SERIAL_SP_PARITY |
        !          1776:                                  SERIAL_SP_BAUD |
        !          1777:                                  SERIAL_SP_DATABITS |
        !          1778:                                  SERIAL_SP_STOPBITS |
        !          1779:                                  SERIAL_SP_HANDSHAKING |
        !          1780:                                  SERIAL_SP_PARITY_CHECK |
        !          1781:                                  SERIAL_SP_CARRIER_DETECT;
        !          1782: 
        !          1783: 
        !          1784:     Properties->SettableData = SERIAL_DATABITS_5 |
        !          1785:                                SERIAL_DATABITS_6 |
        !          1786:                                SERIAL_DATABITS_7 |
        !          1787:                                SERIAL_DATABITS_8;
        !          1788:     Properties->SettableStopParity = SERIAL_STOPBITS_10 |
        !          1789:                                      SERIAL_STOPBITS_15 |
        !          1790:                                      SERIAL_STOPBITS_20 |
        !          1791:                                      SERIAL_PARITY_NONE |
        !          1792:                                      SERIAL_PARITY_ODD  |
        !          1793:                                      SERIAL_PARITY_EVEN |
        !          1794:                                      SERIAL_PARITY_MARK |
        !          1795:                                      SERIAL_PARITY_SPACE;
        !          1796:     Properties->CurrentTxQueue = 0;
        !          1797:     Properties->CurrentRxQueue = Extension->BufferSize;
        !          1798: 
        !          1799: }

unix.superglobalmegacorp.com

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