|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: waitmask.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains the code that is very specific to get/set/wait ! 12: on event mask operations in the serial driver ! 13: ! 14: Author: ! 15: ! 16: Anthony V. Ercolano 26-Sep-1991 ! 17: ! 18: Environment: ! 19: ! 20: Kernel mode ! 21: ! 22: Revision History : ! 23: ! 24: --*/ ! 25: ! 26: #include <stddef.h> ! 27: #include "ntddk.h" ! 28: #include "ntddser.h" ! 29: #include "serial.h" ! 30: #include "serialp.h" ! 31: ! 32: ! 33: BOOLEAN ! 34: SerialGrabWaitFromIsr( ! 35: IN PVOID Context ! 36: ); ! 37: ! 38: BOOLEAN ! 39: SerialGiveWaitToIsr( ! 40: IN PVOID Context ! 41: ); ! 42: ! 43: BOOLEAN ! 44: SerialFinishOldWait( ! 45: IN PVOID Context ! 46: ); ! 47: ! 48: ! 49: NTSTATUS ! 50: SerialStartMask( ! 51: IN PSERIAL_DEVICE_EXTENSION Extension ! 52: ) ! 53: ! 54: /*++ ! 55: ! 56: Routine Description: ! 57: ! 58: This routine is used to process the set mask and wait ! 59: mask ioctls. Calls to this routine are serialized by ! 60: placing irps in the list under the protection of the ! 61: cancel spin lock. ! 62: ! 63: Arguments: ! 64: ! 65: Extension - A pointer to the serial device extension. ! 66: ! 67: Return Value: ! 68: ! 69: Will return pending for everything put the first ! 70: request that we actually process. Even in that ! 71: case it will return pending unless it can complete ! 72: it right away. ! 73: ! 74: ! 75: --*/ ! 76: ! 77: { ! 78: ! 79: // ! 80: // The current stack location. This contains much of the ! 81: // information we need to process this particular request. ! 82: // ! 83: PIO_STACK_LOCATION IrpSp; ! 84: ! 85: PIRP NewIrp; ! 86: ! 87: BOOLEAN SetFirstStatus = FALSE; ! 88: NTSTATUS FirstStatus; ! 89: ! 90: SerialDump( ! 91: SERDIAG3, ! 92: ("SERIAL: In SerialStartMask\n") ! 93: ); ! 94: ! 95: ASSERT(Extension->CurrentMaskIrp); ! 96: ! 97: do { ! 98: ! 99: SerialDump( ! 100: SERDIAG4, ! 101: ("SERIAL: STARMASK - CurrentMaskIrp: %x\n",Extension->CurrentMaskIrp) ! 102: ); ! 103: IrpSp = IoGetCurrentIrpStackLocation(Extension->CurrentMaskIrp); ! 104: ! 105: ASSERT((IrpSp->Parameters.DeviceIoControl.IoControlCode == ! 106: IOCTL_SERIAL_WAIT_ON_MASK) || ! 107: (IrpSp->Parameters.DeviceIoControl.IoControlCode == ! 108: IOCTL_SERIAL_SET_WAIT_MASK)); ! 109: ! 110: if (IrpSp->Parameters.DeviceIoControl.IoControlCode == ! 111: IOCTL_SERIAL_SET_WAIT_MASK) { ! 112: ! 113: SerialDump( ! 114: SERDIAG4, ! 115: ("SERIAL - %x is a SETMASK irp\n",Extension->CurrentMaskIrp) ! 116: ); ! 117: ! 118: // ! 119: // Complete the old wait if there is one. ! 120: // ! 121: ! 122: KeSynchronizeExecution( ! 123: Extension->Interrupt, ! 124: SerialFinishOldWait, ! 125: Extension ! 126: ); ! 127: ! 128: // ! 129: // Any current waits should be on its way to completion ! 130: // at this point. There certainly shouldn't be any ! 131: // irp mask location. ! 132: // ! 133: ! 134: ASSERT(!Extension->IrpMaskLocation); ! 135: ! 136: Extension->CurrentMaskIrp->IoStatus.Status = STATUS_SUCCESS; ! 137: ! 138: if (!SetFirstStatus) { ! 139: ! 140: SerialDump( ! 141: SERDIAG4, ! 142: ("SERIAL: %x was the first irp processed by this\n" ! 143: "------- invocation of startmask\n",Extension->CurrentMaskIrp) ! 144: ); ! 145: FirstStatus = STATUS_SUCCESS; ! 146: SetFirstStatus = TRUE; ! 147: ! 148: } ! 149: ! 150: // ! 151: // The following call will also cause the current ! 152: // call to be completed. ! 153: // ! 154: ! 155: SerialGetNextIrp( ! 156: &Extension->CurrentMaskIrp, ! 157: &Extension->MaskQueue, ! 158: &NewIrp, ! 159: TRUE ! 160: ); ! 161: SerialDump( ! 162: SERDIAG4, ! 163: ("SERIAL: Perhaps another mask irp was found in the queue\n" ! 164: "------- %x/%x <- values should be the same\n", ! 165: Extension->CurrentMaskIrp,NewIrp) ! 166: ); ! 167: ! 168: ! 169: } else { ! 170: ! 171: // ! 172: // First make sure that we have a non-zero mask. ! 173: // If the app queues a wait on a zero mask it can't ! 174: // be statisfied so it makes no sense to start it. ! 175: // ! 176: ! 177: if ((!Extension->IsrWaitMask) || (Extension->CurrentWaitIrp)) { ! 178: ! 179: SerialDump( ! 180: SERDIAG4, ! 181: ("SERIAL: WaitIrp is invalid\n" ! 182: "------- IsrWaitMask: %x\n" ! 183: "------- CurrentWaitIrp: %x\n", ! 184: Extension->IsrWaitMask, ! 185: Extension->CurrentWaitIrp) ! 186: ); ! 187: ! 188: Extension->CurrentMaskIrp->IoStatus.Status = STATUS_INVALID_PARAMETER; ! 189: ! 190: if (!SetFirstStatus) { ! 191: ! 192: SerialDump( ! 193: SERDIAG4, ! 194: ("SERIAL: %x was the first irp processed by this\n" ! 195: "------- invocation of startmask\n",Extension->CurrentMaskIrp) ! 196: ); ! 197: FirstStatus = STATUS_INVALID_PARAMETER; ! 198: SetFirstStatus = TRUE; ! 199: ! 200: } ! 201: ! 202: SerialGetNextIrp( ! 203: &Extension->CurrentMaskIrp, ! 204: &Extension->MaskQueue, ! 205: &NewIrp, ! 206: TRUE ! 207: ); ! 208: SerialDump( ! 209: SERDIAG4, ! 210: ("SERIAL: Perhaps another mask irp was found in the queue\n" ! 211: "------- %x/%x <- values should be the same\n", ! 212: Extension->CurrentMaskIrp,NewIrp) ! 213: ); ! 214: ! 215: } else { ! 216: ! 217: KIRQL OldIrql; ! 218: ! 219: // ! 220: // Make the current mask irp the current wait irp and ! 221: // get a new current mask irp. Note that when we get ! 222: // the new current mask irp we DO NOT complete the ! 223: // old current mask irp (which is now the current wait ! 224: // irp. ! 225: // ! 226: // Then under the protection of the cancel spin lock ! 227: // we check to see if the current wait irp needs to ! 228: // be canceled ! 229: // ! 230: ! 231: IoAcquireCancelSpinLock(&OldIrql); ! 232: ! 233: if (Extension->CurrentMaskIrp->Cancel) { ! 234: ! 235: SerialDump( ! 236: SERDIAG4, ! 237: ("SERIAL: %x irp was already marked as cancelled\n", ! 238: Extension->CurrentMaskIrp) ! 239: ); ! 240: IoReleaseCancelSpinLock(OldIrql); ! 241: Extension->CurrentMaskIrp->IoStatus.Status = STATUS_CANCELLED; ! 242: ! 243: if (!SetFirstStatus) { ! 244: ! 245: SerialDump( ! 246: SERDIAG4, ! 247: ("SERIAL: %x was the first irp processed by this\n" ! 248: "------- invocation of startmask\n",Extension->CurrentMaskIrp) ! 249: ); ! 250: FirstStatus = STATUS_CANCELLED; ! 251: SetFirstStatus = TRUE; ! 252: ! 253: } ! 254: ! 255: SerialGetNextIrp( ! 256: &Extension->CurrentMaskIrp, ! 257: &Extension->MaskQueue, ! 258: &NewIrp, ! 259: TRUE ! 260: ); ! 261: SerialDump( ! 262: SERDIAG4, ! 263: ("SERIAL: Perhaps another mask irp was found in the queue\n" ! 264: "------- %x/%x <- values should be the same\n", ! 265: Extension->CurrentMaskIrp,NewIrp) ! 266: ); ! 267: ! 268: } else { ! 269: ! 270: SerialDump( ! 271: SERDIAG4, ! 272: ("SERIAL: %x will become the current wait irp\n", ! 273: Extension->CurrentMaskIrp) ! 274: ); ! 275: if (!SetFirstStatus) { ! 276: ! 277: SerialDump( ! 278: SERDIAG4, ! 279: ("SERIAL: %x was the first irp processed by this\n" ! 280: "------- invocation of startmask\n",Extension->CurrentMaskIrp) ! 281: ); ! 282: FirstStatus = STATUS_PENDING; ! 283: SetFirstStatus = TRUE; ! 284: ! 285: // ! 286: // If we haven't already set a first status ! 287: // then there is a chance that this packet ! 288: // was never on the queue. We should mark ! 289: // it as pending. ! 290: // ! 291: ! 292: IoMarkIrpPending(Extension->CurrentMaskIrp); ! 293: ! 294: } ! 295: ! 296: // ! 297: // There should never be a mask location when ! 298: // there isn't a current wait irp. At this point ! 299: // there shouldn't be a current wait irp also. ! 300: // ! 301: ! 302: ASSERT(!Extension->IrpMaskLocation); ! 303: ASSERT(!Extension->CurrentWaitIrp); ! 304: ! 305: Extension->CurrentWaitIrp = Extension->CurrentMaskIrp; ! 306: SERIAL_INIT_REFERENCE(Extension->CurrentWaitIrp); ! 307: IoSetCancelRoutine( ! 308: Extension->CurrentWaitIrp, ! 309: SerialCancelWait ! 310: ); ! 311: ! 312: // ! 313: // Since the cancel routine has a reference to ! 314: // the irp we need to update the reference ! 315: // count. ! 316: // ! 317: ! 318: SERIAL_INC_REFERENCE(Extension->CurrentWaitIrp); ! 319: ! 320: KeSynchronizeExecution( ! 321: Extension->Interrupt, ! 322: SerialGiveWaitToIsr, ! 323: Extension ! 324: ); ! 325: ! 326: IoReleaseCancelSpinLock(OldIrql); ! 327: ! 328: SerialGetNextIrp( ! 329: &Extension->CurrentMaskIrp, ! 330: &Extension->MaskQueue, ! 331: &NewIrp, ! 332: FALSE ! 333: ); ! 334: SerialDump( ! 335: SERDIAG4, ! 336: ("SERIAL: Perhaps another mask irp was found in the queue\n" ! 337: "------- %x/%x <- values should be the same\n", ! 338: Extension->CurrentMaskIrp,NewIrp) ! 339: ); ! 340: ! 341: } ! 342: ! 343: } ! 344: ! 345: } ! 346: ! 347: } while (NewIrp); ! 348: ! 349: return FirstStatus; ! 350: ! 351: } ! 352: ! 353: BOOLEAN ! 354: SerialGrabWaitFromIsr( ! 355: IN PVOID Context ! 356: ) ! 357: ! 358: /*++ ! 359: ! 360: Routine Description: ! 361: ! 362: This routine will check to see if the ISR still knows about ! 363: a wait irp by checking to see if the IrpMaskLocation is non-null. ! 364: If it is then it will zero the Irpmasklocation (which in effect ! 365: grabs the irp away from the isr). This routine is only called ! 366: buy the cancel code for the wait. ! 367: ! 368: NOTE: This is called by KeSynchronizeExecution. ! 369: ! 370: Arguments: ! 371: ! 372: Context - A pointer to the device extension ! 373: ! 374: Return Value: ! 375: ! 376: Always FALSE. ! 377: ! 378: --*/ ! 379: ! 380: { ! 381: ! 382: PSERIAL_DEVICE_EXTENSION Extension = Context; ! 383: ! 384: SerialDump( ! 385: SERDIAG3, ! 386: ("SERIAL: In SerialGrabWaitFromIsr\n") ! 387: ); ! 388: ! 389: if (Extension->IrpMaskLocation) { ! 390: ! 391: SerialDump( ! 392: SERDIAG4, ! 393: ("SERIAL: The isr still owns the irp %x, mask location is %x\n" ! 394: "------- and system buffer is %x\n", ! 395: Extension->CurrentWaitIrp,Extension->IrpMaskLocation, ! 396: Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer) ! 397: ); ! 398: ! 399: // ! 400: // The isr still "owns" the irp. ! 401: // ! 402: ! 403: *Extension->IrpMaskLocation = 0; ! 404: Extension->IrpMaskLocation = NULL; ! 405: ! 406: Extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG); ! 407: ! 408: // ! 409: // Since the isr no longer references the irp we need to ! 410: // decrement the reference count. ! 411: // ! 412: ! 413: SERIAL_DEC_REFERENCE(Extension->CurrentWaitIrp); ! 414: ! 415: } ! 416: ! 417: return FALSE; ! 418: } ! 419: ! 420: BOOLEAN ! 421: SerialGiveWaitToIsr( ! 422: IN PVOID Context ! 423: ) ! 424: ! 425: /*++ ! 426: ! 427: Routine Description: ! 428: ! 429: This routine simply sets a variable in the device extension ! 430: so that the isr knows that we have a wait irp. ! 431: ! 432: NOTE: This is called by KeSynchronizeExecution. ! 433: ! 434: NOTE: This routine assumes that it is called with the ! 435: cancel spinlock held. ! 436: ! 437: Arguments: ! 438: ! 439: Context - Simply a pointer to the device extension. ! 440: ! 441: Return Value: ! 442: ! 443: Always FALSE. ! 444: ! 445: --*/ ! 446: ! 447: { ! 448: ! 449: PSERIAL_DEVICE_EXTENSION Extension = Context; ! 450: ! 451: SerialDump( ! 452: SERDIAG3, ! 453: ("SERIAL: In SerialGiveWaitToIsr\n") ! 454: ); ! 455: // ! 456: // There certainly shouldn't be a current mask location at ! 457: // this point since we have a new current wait irp. ! 458: // ! 459: ! 460: ASSERT(!Extension->IrpMaskLocation); ! 461: ! 462: // ! 463: // The isr may or may not actually reference this irp. It ! 464: // won't if the wait can be satisfied immediately. However, ! 465: // since it will then go through the normal completion sequence, ! 466: // we need to have an incremented reference count anyway. ! 467: // ! 468: ! 469: SERIAL_INC_REFERENCE(Extension->CurrentWaitIrp); ! 470: ! 471: if (!Extension->HistoryMask) { ! 472: ! 473: SerialDump( ! 474: SERDIAG4, ! 475: ("SERIAL: No events occured prior to the wait call\n") ! 476: ); ! 477: ! 478: // ! 479: // Although this wait might not be for empty transmit ! 480: // queue, it doesn't hurt anything to set it to false. ! 481: // ! 482: ! 483: Extension->EmptiedTransmit = FALSE; ! 484: ! 485: // ! 486: // Record where the "completion mask" should be set. ! 487: // ! 488: ! 489: Extension->IrpMaskLocation = ! 490: Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer; ! 491: SerialDump( ! 492: SERDIAG4, ! 493: ("SERIAL: The isr owns the irp %x, mask location is %x\n" ! 494: "------- and system buffer is %x\n", ! 495: Extension->CurrentWaitIrp,Extension->IrpMaskLocation, ! 496: Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer) ! 497: ); ! 498: ! 499: } else { ! 500: ! 501: SerialDump( ! 502: SERDIAG4, ! 503: ("SERIAL: %x occurred prior to the wait - starting the\n" ! 504: "------- completion code for %x\n", ! 505: Extension->HistoryMask,Extension->CurrentWaitIrp) ! 506: ); ! 507: *((ULONG *)Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer) = ! 508: Extension->HistoryMask; ! 509: Extension->HistoryMask = 0; ! 510: Extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG); ! 511: Extension->CurrentWaitIrp->IoStatus.Status = STATUS_SUCCESS; ! 512: ! 513: KeInsertQueueDpc( ! 514: &Extension->CommWaitDpc, ! 515: NULL, ! 516: NULL ! 517: ); ! 518: ! 519: } ! 520: ! 521: return FALSE; ! 522: } ! 523: ! 524: BOOLEAN ! 525: SerialFinishOldWait( ! 526: IN PVOID Context ! 527: ) ! 528: ! 529: /*++ ! 530: ! 531: Routine Description: ! 532: ! 533: This routine will check to see if the ISR still knows about ! 534: a wait irp by checking to see if the Irpmasklocation is non-null. ! 535: If it is then it will zero the Irpmasklocation (which in effect ! 536: grabs the irp away from the isr). This routine is only called ! 537: buy the cancel code for the wait. ! 538: ! 539: NOTE: This is called by KeSynchronizeExecution. ! 540: ! 541: Arguments: ! 542: ! 543: Context - A pointer to the device extension ! 544: ! 545: Return Value: ! 546: ! 547: Always FALSE. ! 548: ! 549: --*/ ! 550: ! 551: { ! 552: ! 553: PSERIAL_DEVICE_EXTENSION Extension = Context; ! 554: ! 555: SerialDump( ! 556: SERDIAG3, ! 557: ("SERIAL: In SerialFinishOldWait\n") ! 558: ); ! 559: if (Extension->IrpMaskLocation) { ! 560: ! 561: SerialDump( ! 562: SERDIAG4, ! 563: ("SERIAL: The isr still owns the irp %x, mask location is %x\n" ! 564: "------- and system buffer is %x\n", ! 565: Extension->CurrentWaitIrp,Extension->IrpMaskLocation, ! 566: Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer) ! 567: ); ! 568: // ! 569: // The isr still "owns" the irp. ! 570: // ! 571: ! 572: *Extension->IrpMaskLocation = 0; ! 573: Extension->IrpMaskLocation = NULL; ! 574: ! 575: Extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG); ! 576: ! 577: // ! 578: // We don't decrement the reference since the completion routine ! 579: // will do that. ! 580: // ! 581: ! 582: KeInsertQueueDpc( ! 583: &Extension->CommWaitDpc, ! 584: NULL, ! 585: NULL ! 586: ); ! 587: ! 588: } ! 589: ! 590: // ! 591: // Don't wipe out any historical data we are still interested in. ! 592: // ! 593: ! 594: Extension->HistoryMask &= *((ULONG *)Extension->CurrentMaskIrp-> ! 595: AssociatedIrp.SystemBuffer); ! 596: ! 597: Extension->IsrWaitMask = *((ULONG *)Extension->CurrentMaskIrp-> ! 598: AssociatedIrp.SystemBuffer); ! 599: SerialDump( ! 600: SERDIAG4, ! 601: ("SERIAL: Set mask location of %x, in irp %x, with system buffer of %x\n", ! 602: Extension->IrpMaskLocation, ! 603: Extension->CurrentMaskIrp,Extension->CurrentMaskIrp->AssociatedIrp.SystemBuffer) ! 604: ); ! 605: return FALSE; ! 606: } ! 607: ! 608: VOID ! 609: SerialCancelWait( ! 610: IN PDEVICE_OBJECT DeviceObject, ! 611: IN PIRP Irp ! 612: ) ! 613: ! 614: /*++ ! 615: ! 616: Routine Description: ! 617: ! 618: This routine is used to cancel a irp that is waiting on ! 619: a comm event. ! 620: ! 621: Arguments: ! 622: ! 623: DeviceObject - Pointer to the device object for this device ! 624: ! 625: Irp - Pointer to the IRP for the current request ! 626: ! 627: Return Value: ! 628: ! 629: None. ! 630: ! 631: --*/ ! 632: ! 633: { ! 634: ! 635: PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension; ! 636: ! 637: SerialDump( ! 638: SERDIAG3, ! 639: ("SERIAL: In SerialCancelWait\n") ! 640: ); ! 641: ! 642: SerialDump( ! 643: SERDIAG4, ! 644: ("SERIAL: Canceling wait for irp %x\n",Extension->CurrentWaitIrp) ! 645: ); ! 646: SerialTryToCompleteCurrent( ! 647: Extension, ! 648: SerialGrabWaitFromIsr, ! 649: Irp->CancelIrql, ! 650: STATUS_CANCELLED, ! 651: &Extension->CurrentWaitIrp, ! 652: NULL, ! 653: NULL, ! 654: NULL, ! 655: NULL, ! 656: NULL ! 657: ); ! 658: ! 659: } ! 660: ! 661: VOID ! 662: SerialCompleteWait( ! 663: IN PKDPC Dpc, ! 664: IN PVOID DeferredContext, ! 665: IN PVOID SystemContext1, ! 666: IN PVOID SystemContext2 ! 667: ) ! 668: ! 669: { ! 670: ! 671: PSERIAL_DEVICE_EXTENSION Extension = DeferredContext; ! 672: KIRQL OldIrql; ! 673: ! 674: SerialDump( ! 675: SERDIAG3, ! 676: ("SERIAL: In SerialCompleteWait\n") ! 677: ); ! 678: UNREFERENCED_PARAMETER(Dpc); ! 679: UNREFERENCED_PARAMETER(SystemContext1); ! 680: UNREFERENCED_PARAMETER(SystemContext2); ! 681: ! 682: IoAcquireCancelSpinLock(&OldIrql); ! 683: ! 684: SerialDump( ! 685: SERDIAG4, ! 686: ("SERIAL: Completing wait for irp %x\n",Extension->CurrentWaitIrp) ! 687: ); ! 688: SerialTryToCompleteCurrent( ! 689: Extension, ! 690: NULL, ! 691: OldIrql, ! 692: STATUS_SUCCESS, ! 693: &Extension->CurrentWaitIrp, ! 694: NULL, ! 695: NULL, ! 696: NULL, ! 697: NULL, ! 698: NULL ! 699: ); ! 700: ! 701: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.