|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.