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

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     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.