|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1991, 1992, 1993 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: initunlo.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains the code that is very specific to initialization ! 12: and unload 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: #include "serlog.h" ! 32: ! 33: ! 34: // ! 35: // This is the actual definition of SerialDebugLevel. ! 36: // Note that it is only defined if this is a "debug" ! 37: // build. ! 38: // ! 39: #if DBG ! 40: extern ULONG SerialDebugLevel = 0; ! 41: #endif ! 42: ! 43: static const PHYSICAL_ADDRESS SerialPhysicalZero = {0}; ! 44: ! 45: NTSTATUS ! 46: DriverEntry( ! 47: IN PDRIVER_OBJECT DriverObject, ! 48: IN PUNICODE_STRING RegistryPath ! 49: ); ! 50: ! 51: NTSTATUS ! 52: SerialInitializeController( ! 53: IN PDRIVER_OBJECT DriverObject, ! 54: IN PCONFIG_DATA ConfigData, ! 55: IN BOOLEAN MapInterruptStatus, ! 56: OUT PSERIAL_DEVICE_EXTENSION *DeviceExtension ! 57: ); ! 58: ! 59: BOOLEAN ! 60: SerialDoesPortExist( ! 61: IN PSERIAL_DEVICE_EXTENSION Extension, ! 62: PUNICODE_STRING InsertString, ! 63: IN ULONG ForceFifo ! 64: ); ! 65: ! 66: VOID ! 67: SerialCleanupMultiPort( ! 68: PSERIAL_DEVICE_EXTENSION *ExtensionList, ! 69: ULONG NumberOfDevices ! 70: ); ! 71: ! 72: VOID ! 73: SerialGetConfigInfo( ! 74: IN PDRIVER_OBJECT DriverObject, ! 75: IN PUNICODE_STRING RegistryPath, ! 76: ULONG ForceFifoEnableDefault, ! 77: ULONG RxFifoDefault, ! 78: OUT PLIST_ENTRY ConfigList ! 79: ); ! 80: ! 81: BOOLEAN ! 82: SerialPutInConfigList( ! 83: IN PDRIVER_OBJECT DriverObject, ! 84: IN OUT PLIST_ENTRY ConfigList, ! 85: IN PCONFIG_DATA New ! 86: ); ! 87: ! 88: BOOLEAN ! 89: SerialResetSynch( ! 90: IN PVOID Context ! 91: ); ! 92: ! 93: PVOID ! 94: SerialGetMappedAddress( ! 95: IN INTERFACE_TYPE BusType, ! 96: IN ULONG BusNumber, ! 97: PHYSICAL_ADDRESS IoAddress, ! 98: ULONG NumberOfBytes, ! 99: ULONG AddressSpace, ! 100: PBOOLEAN MappedAddress ! 101: ); ! 102: ! 103: VOID ! 104: SerialSetupExternalNaming( ! 105: IN PSERIAL_DEVICE_EXTENSION Extension ! 106: ); ! 107: ! 108: VOID ! 109: SerialCleanupExternalNaming( ! 110: IN PSERIAL_DEVICE_EXTENSION Extension ! 111: ); ! 112: ! 113: typedef enum _SERIAL_MEM_COMPARES { ! 114: AddressesAreEqual, ! 115: AddressesOverlap, ! 116: AddressesAreDisjoint ! 117: } SERIAL_MEM_COMPARES,*PSERIAL_MEM_COMPARES; ! 118: ! 119: SERIAL_MEM_COMPARES ! 120: SerialMemCompare( ! 121: IN PHYSICAL_ADDRESS A, ! 122: IN ULONG SpanOfA, ! 123: IN PHYSICAL_ADDRESS B, ! 124: IN ULONG SpanOfB ! 125: ); ! 126: ! 127: VOID ! 128: SerialPropagateDeleteSharers( ! 129: IN PSERIAL_DEVICE_EXTENSION Extension, ! 130: IN OUT PULONG CountSoFar OPTIONAL, ! 131: IN PKINTERRUPT Interrupt OPTIONAL ! 132: ); ! 133: ! 134: VOID ! 135: SerialInitializeRootInterrupt( ! 136: IN PDRIVER_OBJECT DriverObject, ! 137: IN PCONFIG_DATA ConfigData ! 138: ); ! 139: ! 140: NTSTATUS ! 141: SerialInitializeRootMultiPort( ! 142: IN PDRIVER_OBJECT DriverObject, ! 143: IN PCONFIG_DATA ConfigData, ! 144: OUT PSERIAL_DEVICE_EXTENSION *DeviceExtension ! 145: ); ! 146: ! 147: NTSTATUS ! 148: SerialInitializeOneController( ! 149: IN PDRIVER_OBJECT DriverObject, ! 150: IN PCONFIG_DATA ConfigData, ! 151: IN BOOLEAN MapInterruptStatus, ! 152: OUT PSERIAL_DEVICE_EXTENSION *Extension ! 153: ); ! 154: ! 155: VOID ! 156: SerialLogError( ! 157: IN PDRIVER_OBJECT DriverObject, ! 158: IN PDEVICE_OBJECT DeviceObject OPTIONAL, ! 159: IN PHYSICAL_ADDRESS P1, ! 160: IN PHYSICAL_ADDRESS P2, ! 161: IN ULONG SequenceNumber, ! 162: IN UCHAR MajorFunctionCode, ! 163: IN UCHAR RetryCount, ! 164: IN ULONG UniqueErrorValue, ! 165: IN NTSTATUS FinalStatus, ! 166: IN NTSTATUS SpecificIOStatus, ! 167: IN ULONG LengthOfInsert1, ! 168: IN PWCHAR Insert1, ! 169: IN ULONG LengthOfInsert2, ! 170: IN PWCHAR Insert2 ! 171: ); ! 172: ! 173: NTSTATUS ! 174: SerialItemCallBack( ! 175: IN PVOID Context, ! 176: IN PUNICODE_STRING PathName, ! 177: IN INTERFACE_TYPE BusType, ! 178: IN ULONG BusNumber, ! 179: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 180: IN CONFIGURATION_TYPE ControllerType, ! 181: IN ULONG ControllerNumber, ! 182: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 183: IN CONFIGURATION_TYPE PeripheralType, ! 184: IN ULONG PeripheralNumber, ! 185: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 186: ); ! 187: ! 188: NTSTATUS ! 189: SerialConfigCallBack( ! 190: IN PVOID Context, ! 191: IN PUNICODE_STRING PathName, ! 192: IN INTERFACE_TYPE BusType, ! 193: IN ULONG BusNumber, ! 194: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 195: IN CONFIGURATION_TYPE ControllerType, ! 196: IN ULONG ControllerNumber, ! 197: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 198: IN CONFIGURATION_TYPE PeripheralType, ! 199: IN ULONG PeripheralNumber, ! 200: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 201: ); ! 202: ! 203: VOID ! 204: SerialUnReportResourcesDevice( ! 205: IN PSERIAL_DEVICE_EXTENSION Extension ! 206: ); ! 207: ! 208: VOID ! 209: SerialReportResourcesDevice( ! 210: IN PSERIAL_DEVICE_EXTENSION Extension, ! 211: OUT BOOLEAN *ConflictDetected ! 212: ); ! 213: ! 214: // ! 215: // This is exported from the kernel. It is used to point ! 216: // to the address that the kernel debugger is using. ! 217: // ! 218: extern PUCHAR *KdComPortInUse; ! 219: ! 220: #ifdef ALLOC_PRAGMA ! 221: #pragma alloc_text(init,DriverEntry) ! 222: #pragma alloc_text(init,SerialInitializeRootInterrupt) ! 223: #pragma alloc_text(init,SerialInitializeRootMultiPort) ! 224: #pragma alloc_text(init,SerialInitializeOneController) ! 225: #pragma alloc_text(init,SerialInitializeController) ! 226: #pragma alloc_text(init,SerialDoesPortExist) ! 227: #pragma alloc_text(init,SerialItemCallBack) ! 228: #pragma alloc_text(init,SerialConfigCallBack) ! 229: #pragma alloc_text(init,SerialGetConfigInfo) ! 230: #pragma alloc_text(init,SerialPutInConfigList) ! 231: #pragma alloc_text(init,SerialGetMappedAddress) ! 232: #pragma alloc_text(init,SerialSetupExternalNaming) ! 233: #pragma alloc_text(init,SerialMemCompare) ! 234: #pragma alloc_text(init,SerialReportResourcesDevice) ! 235: #endif ! 236: ! 237: ! 238: NTSTATUS ! 239: DriverEntry( ! 240: IN PDRIVER_OBJECT DriverObject, ! 241: IN PUNICODE_STRING RegistryPath ! 242: ) ! 243: ! 244: /*++ ! 245: ! 246: Routine Description: ! 247: ! 248: The entry point that the system point calls to initialize ! 249: any driver. ! 250: ! 251: This routine will gather the configuration information, ! 252: report resource usage, attempt to initialize all serial ! 253: devices, connect to interrupts for ports. If the above ! 254: goes reasonably well it will fill in the dispatch points, ! 255: reset the serial devices and then return to the system. ! 256: ! 257: Arguments: ! 258: ! 259: DriverObject - Just what it says, really of little use ! 260: to the driver itself, it is something that the IO system ! 261: cares more about. ! 262: ! 263: PathToRegistry - points to the entry for this driver ! 264: in the current control set of the registry. ! 265: ! 266: Return Value: ! 267: ! 268: STATUS_SUCCESS if we could initialize a single device, ! 269: otherwise STATUS_SERIAL_NO_DEVICE_INITED. ! 270: ! 271: --*/ ! 272: ! 273: { ! 274: ! 275: // ! 276: // Holds status information return by various OS and driver ! 277: // initialization routines. ! 278: // ! 279: NTSTATUS status; ! 280: ! 281: // ! 282: // List head for configuration records. ! 283: // ! 284: LIST_ENTRY configList; ! 285: ! 286: // ! 287: // Pointer to a device object in the device object chain ! 288: // hanging off of the driver object. ! 289: // ! 290: PDEVICE_OBJECT currentDevice; ! 291: ! 292: // ! 293: // Holds a pointer to a ulong that the Io system maintains ! 294: // of the count of serial devices. ! 295: // ! 296: PULONG countSoFar; ! 297: ! 298: // ! 299: // We use this to query into the registry as to whether we ! 300: // should break at driver entry. ! 301: // ! 302: RTL_QUERY_REGISTRY_TABLE paramTable[5]; ! 303: ULONG zero = 0; ! 304: ULONG debugLevel = 0; ! 305: ULONG shouldBreak = 0; ! 306: ULONG forceFifoEnableDefault; ! 307: ULONG rxFIFODefault; ! 308: ULONG notThereDefault = 1234567; ! 309: PWCHAR path; ! 310: ! 311: // ! 312: // Since the registry path parameter is a "counted" UNICODE string, it ! 313: // might not be zero terminated. For a very short time allocate memory ! 314: // to hold the registry path zero terminated so that we can use it to ! 315: // delve into the registry. ! 316: // ! 317: // NOTE NOTE!!!! This is not an architected way of breaking into ! 318: // a driver. It happens to work for this driver because the author ! 319: // likes to do things this way. ! 320: // ! 321: ! 322: if (path = ExAllocatePool( ! 323: PagedPool, ! 324: RegistryPath->Length+sizeof(WCHAR) ! 325: )) { ! 326: ! 327: RtlZeroMemory( ! 328: ¶mTable[0], ! 329: sizeof(paramTable) ! 330: ); ! 331: RtlZeroMemory( ! 332: path, ! 333: RegistryPath->Length+sizeof(WCHAR) ! 334: ); ! 335: RtlMoveMemory( ! 336: path, ! 337: RegistryPath->Buffer, ! 338: RegistryPath->Length ! 339: ); ! 340: paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 341: paramTable[0].Name = L"BreakOnEntry"; ! 342: paramTable[0].EntryContext = &shouldBreak; ! 343: paramTable[0].DefaultType = REG_DWORD; ! 344: paramTable[0].DefaultData = &zero; ! 345: paramTable[0].DefaultLength = sizeof(ULONG); ! 346: paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 347: paramTable[1].Name = L"DebugLevel"; ! 348: paramTable[1].EntryContext = &debugLevel; ! 349: paramTable[1].DefaultType = REG_DWORD; ! 350: paramTable[1].DefaultData = &zero; ! 351: paramTable[1].DefaultLength = sizeof(ULONG); ! 352: paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 353: paramTable[2].Name = L"ForceFifoEnable"; ! 354: paramTable[2].EntryContext = &forceFifoEnableDefault; ! 355: paramTable[2].DefaultType = REG_DWORD; ! 356: paramTable[2].DefaultData = ¬ThereDefault; ! 357: paramTable[2].DefaultLength = sizeof(ULONG); ! 358: paramTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 359: paramTable[3].Name = L"RxFIFO"; ! 360: paramTable[3].EntryContext = &rxFIFODefault; ! 361: paramTable[3].DefaultType = REG_DWORD; ! 362: paramTable[3].DefaultData = ¬ThereDefault; ! 363: paramTable[3].DefaultLength = sizeof(ULONG); ! 364: ! 365: if (!NT_SUCCESS(RtlQueryRegistryValues( ! 366: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, ! 367: path, ! 368: ¶mTable[0], ! 369: NULL, ! 370: NULL ! 371: ))) { ! 372: ! 373: shouldBreak = 0; ! 374: debugLevel = 0; ! 375: ! 376: } ! 377: ! 378: } ! 379: ! 380: #if DBG ! 381: SerialDebugLevel = debugLevel; ! 382: #endif ! 383: ! 384: if (shouldBreak) { ! 385: ! 386: DbgBreakPoint(); ! 387: ! 388: } ! 389: ! 390: // ! 391: // Check to see if there was a forcefifo or an rxfifo size. ! 392: // If there isn't then write out values so that they could ! 393: // be adjusted later. ! 394: // ! 395: ! 396: if (forceFifoEnableDefault == notThereDefault) { ! 397: ! 398: forceFifoEnableDefault = 1; ! 399: RtlWriteRegistryValue( ! 400: RTL_REGISTRY_ABSOLUTE, ! 401: path, ! 402: L"ForceFifoEnable", ! 403: REG_DWORD, ! 404: &forceFifoEnableDefault, ! 405: sizeof(ULONG) ! 406: ); ! 407: ! 408: } ! 409: ! 410: if (rxFIFODefault == notThereDefault) { ! 411: ! 412: rxFIFODefault = 8; ! 413: RtlWriteRegistryValue( ! 414: RTL_REGISTRY_ABSOLUTE, ! 415: path, ! 416: L"RxFIFO", ! 417: REG_DWORD, ! 418: &rxFIFODefault, ! 419: sizeof(ULONG) ! 420: ); ! 421: ! 422: } ! 423: ! 424: ! 425: ! 426: // ! 427: // We don't need that path anymore. ! 428: // ! 429: ! 430: if (path) { ! 431: ! 432: ExFreePool(path); ! 433: ! 434: } ! 435: ! 436: // ! 437: // Just dump out how big the extension is. ! 438: // ! 439: ! 440: SerialDump( ! 441: SERDIAG1, ! 442: ("SERIAL: The number of bytes in the extension is: %d\n", ! 443: sizeof(SERIAL_DEVICE_EXTENSION)) ! 444: ); ! 445: ! 446: ! 447: countSoFar = &IoGetConfigurationInformation()->SerialCount; ! 448: ! 449: SerialGetConfigInfo( ! 450: DriverObject, ! 451: RegistryPath, ! 452: forceFifoEnableDefault, ! 453: rxFIFODefault, ! 454: &configList ! 455: ); ! 456: ! 457: // ! 458: // Initialize each item in the list of configuration records. ! 459: // ! 460: ! 461: while (!IsListEmpty(&configList)) { ! 462: ! 463: PCONFIG_DATA currentConfig; ! 464: PLIST_ENTRY head; ! 465: ! 466: head = RemoveHeadList(&configList); ! 467: ! 468: currentConfig = CONTAINING_RECORD( ! 469: head, ! 470: CONFIG_DATA, ! 471: ConfigList ! 472: ); ! 473: ! 474: SerialInitializeRootInterrupt( ! 475: DriverObject, ! 476: currentConfig ! 477: ); ! 478: ! 479: } ! 480: ! 481: // ! 482: // We've initialized all of the hardware that this driver ! 483: // will ever know about. All of the hardware that we know ! 484: // about is set up to NOT interrupt. We now go through ! 485: // all of the devices and connect an interrupt object for ! 486: // all. ! 487: // ! 488: ! 489: currentDevice = DriverObject->DeviceObject; ! 490: ! 491: while (currentDevice) { ! 492: ! 493: PSERIAL_DEVICE_EXTENSION extension = currentDevice->DeviceExtension; ! 494: ! 495: // ! 496: // This loop will only connect the interrupt for the ! 497: // "root" controller. When we initialize a root controller ! 498: // we then propagate that interrupt object to all associate ! 499: // controllers. If a device doesn't already have an interrupt ! 500: // and it has an isr then we attempt to connect to the ! 501: // interrupt. Note that if we fail to connect to an interrupt ! 502: // we will delete all of the associated devices. ! 503: // ! 504: ! 505: if ((!extension->Interrupt) && ! 506: (extension->OurIsr)) { ! 507: ! 508: SerialDump( ! 509: SERDIAG5, ! 510: ("SERIAL: About to connect to interrupt for port %wZ\n" ! 511: "------- address of extension is %x\n", ! 512: &extension->DeviceName,extension) ! 513: ); ! 514: status = IoConnectInterrupt( ! 515: &extension->Interrupt, ! 516: extension->OurIsr, ! 517: extension->OurIsrContext, ! 518: NULL, ! 519: extension->Vector, ! 520: extension->Irql, ! 521: extension->Irql, ! 522: extension->InterruptMode, ! 523: extension->InterruptShareable, ! 524: extension->ProcessorAffinity, ! 525: FALSE ! 526: ); ! 527: ! 528: if (!NT_SUCCESS(status)) { ! 529: ! 530: // ! 531: // Hmmm, how'd that happen? Somebody either ! 532: // didn't report their resources, or they ! 533: // sneaked in since the last time I looked. ! 534: // ! 535: // Oh well, delete this device as well as ! 536: // any of the devices that were hoping to ! 537: // share this interrupt. ! 538: // ! 539: ! 540: SerialDump( ! 541: SERERRORS, ! 542: ("SERIAL: Couldn't connect to interrupt for %wZ\n", ! 543: &extension->DeviceName) ! 544: ); ! 545: SerialLogError( ! 546: extension->DeviceObject->DriverObject, ! 547: extension->DeviceObject, ! 548: extension->OriginalController, ! 549: SerialPhysicalZero, ! 550: 0, ! 551: 0, ! 552: 0, ! 553: 1, ! 554: status, ! 555: SERIAL_UNREPORTED_IRQL_CONFLICT, ! 556: extension->SymbolicLinkName.Length+sizeof(WCHAR), ! 557: extension->SymbolicLinkName.Buffer, ! 558: 0, ! 559: NULL ! 560: ); ! 561: SerialPropagateDeleteSharers( ! 562: extension, ! 563: NULL, ! 564: NULL ! 565: ); ! 566: ! 567: // ! 568: // The above call deleted all the associated ! 569: // device objects. Who knows what the device ! 570: // list looks like now! Start over from ! 571: // the beginning of the device list. ! 572: // ! 573: ! 574: currentDevice = DriverObject->DeviceObject; ! 575: ! 576: } else { ! 577: ! 578: SerialPropagateDeleteSharers( ! 579: extension, ! 580: countSoFar, ! 581: extension->Interrupt ! 582: ); ! 583: ! 584: currentDevice = DriverObject->DeviceObject; ! 585: ! 586: } ! 587: ! 588: } else { ! 589: ! 590: // ! 591: // We've already done this device. We can go on ! 592: // to the next device. ! 593: // ! 594: ! 595: currentDevice = currentDevice->NextDevice; ! 596: ! 597: } ! 598: ! 599: } ! 600: ! 601: // ! 602: // Well if we connected to any interrupts then we should ! 603: // have some device objects. Go through all of the devices ! 604: // and reset each device. ! 605: // ! 606: ! 607: currentDevice = DriverObject->DeviceObject; ! 608: ! 609: while (currentDevice) { ! 610: ! 611: PDEVICE_OBJECT nextDevice = currentDevice->NextDevice; ! 612: PSERIAL_DEVICE_EXTENSION extension = currentDevice->DeviceExtension; ! 613: ! 614: // ! 615: // While the device isn't open, disable all interrupts. ! 616: // ! 617: ! 618: DISABLE_ALL_INTERRUPTS(extension->Controller); ! 619: ! 620: if (extension->Jensen) { ! 621: ! 622: WRITE_MODEM_CONTROL( ! 623: extension->Controller, ! 624: (UCHAR)SERIAL_MCR_OUT2 ! 625: ); ! 626: ! 627: } else { ! 628: ! 629: WRITE_MODEM_CONTROL( ! 630: extension->Controller, ! 631: (UCHAR)0 ! 632: ); ! 633: ! 634: } ! 635: ! 636: // ! 637: // This should set up everything as it should be when ! 638: // a device is to be opened. We do need to lower the ! 639: // modem lines, and disable the stupid fifo so that it ! 640: // will show up if the user boots to dos. ! 641: // ! 642: ! 643: KeSynchronizeExecution( ! 644: extension->Interrupt, ! 645: SerialReset, ! 646: currentDevice->DeviceExtension ! 647: ); ! 648: KeSynchronizeExecution( //Disables the fifo. ! 649: extension->Interrupt, ! 650: SerialMarkClose, ! 651: currentDevice->DeviceExtension ! 652: ); ! 653: KeSynchronizeExecution( ! 654: extension->Interrupt, ! 655: SerialClrRTS, ! 656: currentDevice->DeviceExtension ! 657: ); ! 658: KeSynchronizeExecution( ! 659: extension->Interrupt, ! 660: SerialClrDTR, ! 661: currentDevice->DeviceExtension ! 662: ); ! 663: ! 664: ! 665: currentDevice = nextDevice; ! 666: ! 667: } ! 668: ! 669: if (DriverObject->DeviceObject) { ! 670: ! 671: status = STATUS_SUCCESS; ! 672: ! 673: // ! 674: // Initialize the Driver Object with driver's entry points ! 675: // ! 676: ! 677: DriverObject->DriverUnload = SerialUnload; ! 678: DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = SerialFlush; ! 679: DriverObject->MajorFunction[IRP_MJ_WRITE] = SerialWrite; ! 680: DriverObject->MajorFunction[IRP_MJ_READ] = SerialRead; ! 681: DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SerialIoControl; ! 682: DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialCreateOpen; ! 683: DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialClose; ! 684: DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SerialCleanup; ! 685: DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = ! 686: SerialQueryInformationFile; ! 687: DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = ! 688: SerialSetInformationFile; ! 689: ! 690: } else { ! 691: ! 692: status = STATUS_SERIAL_NO_DEVICE_INITED; ! 693: ! 694: } ! 695: ! 696: return status; ! 697: } ! 698: ! 699: VOID ! 700: SerialPropagateDeleteSharers( ! 701: IN PSERIAL_DEVICE_EXTENSION Extension, ! 702: IN OUT PULONG CountSoFar OPTIONAL, ! 703: IN PKINTERRUPT Interrupt OPTIONAL ! 704: ) ! 705: ! 706: /*++ ! 707: ! 708: Routine Description: ! 709: ! 710: This routine will either propagate the interrupt object ! 711: to all extensions sharing the same interrupt, or it will ! 712: delete all devices sharing the same interrupt. ! 713: ! 714: Arguments: ! 715: ! 716: Extension - "Listhead" of all devices sharing the same ! 717: interrupt. ! 718: ! 719: CountSoFar - If interrupt is present and this is present, ! 720: we will increment the longword pointed to ! 721: by this pointer for each device extension ! 722: we stick the interrupt into. ! 723: ! 724: If interrupt is *not* present and this ! 725: pointer *is* present, we will decrement the ! 726: longword pointed to by this value for ! 727: each device we delete. ! 728: ! 729: If this isn't present, well, then, I guess ! 730: we won't do anything with it. ! 731: ! 732: Interrupt - If this is present, we propagate it to ! 733: all devices on that want to share the interrupt. ! 734: ! 735: ! 736: Return Value: ! 737: ! 738: None. ! 739: ! 740: --*/ ! 741: ! 742: { ! 743: ! 744: ASSERT(Extension->OurIsr); ! 745: ! 746: SerialDump( ! 747: SERDIAG3, ! 748: ("SERIAL: In SerialPropagateDeleteSharers\n" ! 749: "------- Extension: %x CountSoFar: %d Interrupt: %x\n", ! 750: Extension,*CountSoFar,Interrupt) ! 751: ); ! 752: ! 753: if (Interrupt) { ! 754: ! 755: PLIST_ENTRY currentEntry; ! 756: PLIST_ENTRY firstEntry; ! 757: ! 758: SerialDump( ! 759: SERDIAG5, ! 760: ("SERIAL: In the report propagate path\n") ! 761: ); ! 762: ! 763: // ! 764: // Were supposed to place the interrupt object ! 765: // in every associated device object. ! 766: // ! 767: ! 768: currentEntry = &Extension->CommonInterruptObject; ! 769: firstEntry = currentEntry; ! 770: ! 771: do { ! 772: ! 773: PSERIAL_DEVICE_EXTENSION currentExtension; ! 774: ! 775: currentExtension = CONTAINING_RECORD( ! 776: currentEntry, ! 777: SERIAL_DEVICE_EXTENSION, ! 778: CommonInterruptObject ! 779: ); ! 780: ! 781: currentExtension->Interrupt = Interrupt; ! 782: ! 783: ! 784: if (ARGUMENT_PRESENT(CountSoFar)) { ! 785: ! 786: *CountSoFar += 1; ! 787: ! 788: } ! 789: ! 790: currentEntry = currentExtension->CommonInterruptObject.Flink; ! 791: ! 792: } while (currentEntry != firstEntry); ! 793: ! 794: } else { ! 795: ! 796: LIST_ENTRY listHead; ! 797: ! 798: // ! 799: // We are supposed to delete all of the devices ! 800: // in the linked list. ! 801: // ! 802: // First we make a local list head that doesn't ! 803: // have the current extension as part of the list. ! 804: // ! 805: // The we cleanup and delete the "root" device. ! 806: // ! 807: // The we traverse all of the associated device ! 808: // extensions and null out the interrupt object ! 809: // (this way subsequent cleanup code won't attempt ! 810: // to disconnect the interrupt object) then we ! 811: // cleanup and delete the device. ! 812: // ! 813: ! 814: SerialDump( ! 815: SERDIAG5, ! 816: ("SERIAL: In the deletion/unreport path\n") ! 817: ); ! 818: ! 819: InitializeListHead(&listHead); ! 820: ! 821: if (!IsListEmpty(&Extension->CommonInterruptObject)) { ! 822: ! 823: PLIST_ENTRY old = Extension->CommonInterruptObject.Flink; ! 824: ! 825: RemoveEntryList(&Extension->CommonInterruptObject); ! 826: InsertTailList( ! 827: old, ! 828: &listHead ! 829: ); ! 830: ! 831: } ! 832: ! 833: if (ARGUMENT_PRESENT(CountSoFar)) { ! 834: ! 835: // ! 836: // An implication of decrementing the ! 837: // count is that the device has reported ! 838: // it's resources already. Now unreport ! 839: // them. ! 840: // ! 841: ! 842: *CountSoFar -= 1; ! 843: SerialUnReportResourcesDevice(Extension); ! 844: ! 845: } ! 846: ! 847: SerialCleanupDevice(Extension); ! 848: IoDeleteDevice(Extension->DeviceObject); ! 849: ! 850: while (!IsListEmpty(&listHead)) { ! 851: ! 852: PLIST_ENTRY head; ! 853: PSERIAL_DEVICE_EXTENSION currentExtension; ! 854: ! 855: head = RemoveHeadList(&listHead); ! 856: ! 857: currentExtension = CONTAINING_RECORD( ! 858: head, ! 859: SERIAL_DEVICE_EXTENSION, ! 860: CommonInterruptObject ! 861: ); ! 862: ! 863: currentExtension->Interrupt = NULL; ! 864: ! 865: if (ARGUMENT_PRESENT(CountSoFar)) { ! 866: ! 867: *CountSoFar -= 1; ! 868: SerialUnReportResourcesDevice(currentExtension); ! 869: ! 870: } ! 871: ! 872: SerialCleanupDevice(currentExtension); ! 873: IoDeleteDevice(currentExtension->DeviceObject); ! 874: ! 875: } ! 876: ! 877: } ! 878: ! 879: } ! 880: ! 881: VOID ! 882: SerialInitializeRootInterrupt( ! 883: IN PDRIVER_OBJECT DriverObject, ! 884: IN PCONFIG_DATA ConfigData ! 885: ) ! 886: ! 887: /*++ ! 888: ! 889: Routine Description: ! 890: ! 891: This routine attempts to build a list suitable for dispatching ! 892: to multiple extensions for devices that want to share an interrupt. ! 893: Note that this includes the degenerate case of a single port who ! 894: wont be sharing. ! 895: ! 896: Arguments: ! 897: ! 898: DriverObject - Simply passed on to the controller initialization. ! 899: ! 900: ConfigData - Root of a "tree" of configuration records. ! 901: ! 902: Return Value: ! 903: ! 904: None. ! 905: ! 906: --*/ ! 907: ! 908: { ! 909: ! 910: PSERIAL_DEVICE_EXTENSION rootExtension = NULL; ! 911: PCONFIG_DATA originalConfig = ConfigData; ! 912: PCONFIG_DATA currentConfig = ConfigData; ! 913: LIST_ENTRY listHead; ! 914: ! 915: SerialDump( ! 916: SERDIAG3, ! 917: ("SERIAL: In SerialInitializeRootInterrupt\n") ! 918: ); ! 919: ! 920: // ! 921: // This makes the listhead imbedded in the root config ! 922: // record a local list head. That list no longer has the ! 923: // original config record as part of the list. ! 924: // ! 925: ! 926: InitializeListHead(&listHead); ! 927: ! 928: if (!IsListEmpty(&ConfigData->SameInterrupt)) { ! 929: ! 930: PLIST_ENTRY old = ConfigData->SameInterrupt.Flink; ! 931: ! 932: RemoveEntryList(&ConfigData->SameInterrupt); ! 933: InsertTailList( ! 934: old, ! 935: &listHead ! 936: ); ! 937: ! 938: } ! 939: ! 940: // ! 941: // If we are on a MicroChannel bus then all the configs can simply ! 942: // share the interrupt. ! 943: // ! 944: ! 945: if (ConfigData->InterfaceType == MicroChannel) { ! 946: ! 947: // ! 948: // We know that all of the configs on this "chain" ! 949: // are using the MicroChannel. ! 950: // ! 951: ! 952: while (currentConfig) { ! 953: ! 954: if (!IsListEmpty(¤tConfig->SameInterruptStatus)) { ! 955: ! 956: // ! 957: // This is a multiport card, call its intialization. ! 958: // ! 959: ! 960: SerialDump( ! 961: SERDIAG5, ! 962: ("SERIAL: Attempting to make %wZ with controller at %x\n" ! 963: "------- and status at %x a same interrupt root of multiports\n" ! 964: "------- On a MicroChannel.\n", ! 965: ¤tConfig->NtNameForPort,currentConfig->Controller.LowPart, ! 966: currentConfig->InterruptStatus.LowPart) ! 967: ); ! 968: SerialInitializeRootMultiPort( ! 969: DriverObject, ! 970: currentConfig, ! 971: &rootExtension ! 972: ); ! 973: ! 974: } else { ! 975: ! 976: SerialDump( ! 977: SERDIAG5, ! 978: ("SERIAL: Attempting to make %wZ with controller at %x\n" ! 979: "------- A same interrupt single controller On a MicroChannel.\n", ! 980: ¤tConfig->NtNameForPort,currentConfig->Controller.LowPart) ! 981: ); ! 982: SerialInitializeOneController( ! 983: DriverObject, ! 984: currentConfig, ! 985: FALSE, ! 986: &rootExtension ! 987: ); ! 988: ! 989: } ! 990: SerialDump( ! 991: SERDIAG5, ! 992: ("SERIAL: It came back with a same interrupt rootExtension of %x\n", ! 993: rootExtension) ! 994: ); ! 995: ! 996: if (!IsListEmpty(&listHead)) { ! 997: ! 998: PLIST_ENTRY head; ! 999: ! 1000: head = RemoveHeadList(&listHead); ! 1001: ! 1002: currentConfig = CONTAINING_RECORD( ! 1003: head, ! 1004: CONFIG_DATA, ! 1005: SameInterrupt ! 1006: ); ! 1007: ! 1008: } else { ! 1009: ! 1010: currentConfig = NULL; ! 1011: rootExtension = NULL; ! 1012: ! 1013: } ! 1014: ! 1015: } ! 1016: ! 1017: ! 1018: } else { ! 1019: ! 1020: // ! 1021: // We have to set up to do "shareing" of interrupt resources. ! 1022: // ! 1023: ! 1024: // ! 1025: // We first keep trying to initialize one of the ! 1026: // configs on the chain until one succeeds. ! 1027: // ! 1028: ! 1029: while ((!rootExtension) && currentConfig) { ! 1030: ! 1031: NTSTATUS status; ! 1032: ! 1033: if (!IsListEmpty(¤tConfig->SameInterruptStatus)) { ! 1034: ! 1035: // ! 1036: // This is a multiport card, call its intialization. ! 1037: // ! 1038: ! 1039: SerialDump( ! 1040: SERDIAG5, ! 1041: ("SERIAL: Attempting to make %wZ with controller at %x\n" ! 1042: "------- and status at %x a same interrupt sharer root controller\n", ! 1043: ¤tConfig->NtNameForPort,currentConfig->Controller.LowPart, ! 1044: currentConfig->InterruptStatus.LowPart) ! 1045: ); ! 1046: status = SerialInitializeRootMultiPort( ! 1047: DriverObject, ! 1048: currentConfig, ! 1049: &rootExtension ! 1050: ); ! 1051: ! 1052: } else { ! 1053: ! 1054: SerialDump( ! 1055: SERDIAG5, ! 1056: ("SERIAL: Attempting to make %wZ with controller at %x\n" ! 1057: "------- A single same interrupt sharer root controller.\n", ! 1058: ¤tConfig->NtNameForPort,currentConfig->Controller.LowPart) ! 1059: ); ! 1060: status = SerialInitializeOneController( ! 1061: DriverObject, ! 1062: currentConfig, ! 1063: FALSE, ! 1064: &rootExtension ! 1065: ); ! 1066: ! 1067: } ! 1068: ! 1069: SerialDump( ! 1070: SERDIAG5, ! 1071: ("SERIAL: It came back with a same interrupt rootExtension of %x\n", ! 1072: rootExtension) ! 1073: ); ! 1074: ! 1075: if (!NT_SUCCESS(status)) { ! 1076: ! 1077: // ! 1078: // Well that one didn't work. Try the next one. ! 1079: // ! 1080: ! 1081: if (!IsListEmpty(&listHead)) { ! 1082: ! 1083: PLIST_ENTRY head; ! 1084: ! 1085: head = RemoveHeadList(&listHead); ! 1086: ! 1087: currentConfig = CONTAINING_RECORD( ! 1088: head, ! 1089: CONFIG_DATA, ! 1090: SameInterrupt ! 1091: ); ! 1092: ! 1093: } else { ! 1094: ! 1095: currentConfig = NULL; ! 1096: rootExtension = NULL; ! 1097: ! 1098: } ! 1099: ! 1100: } else { ! 1101: ! 1102: // ! 1103: // We save off the isr to use and the context to the ! 1104: // isr into the following fields. Unless the ! 1105: // device is actually sharing the interrupt with ! 1106: // another "card" this field will not be ! 1107: // needed. ! 1108: // ! 1109: ! 1110: rootExtension->TopLevelOurIsr = rootExtension->OurIsr; ! 1111: rootExtension->TopLevelOurIsrContext = rootExtension->OurIsrContext; ! 1112: ! 1113: } ! 1114: ! 1115: ! 1116: } ! 1117: ! 1118: if (rootExtension) { ! 1119: ! 1120: // ! 1121: // We have a root extension! Now try to ! 1122: // all intialize all the other configs on this ! 1123: // interrupt. ! 1124: // ! 1125: ! 1126: ULONG numberOfSharers = 1; ! 1127: ! 1128: while (!IsListEmpty(&listHead)) { ! 1129: ! 1130: NTSTATUS status; ! 1131: PLIST_ENTRY head; ! 1132: PSERIAL_DEVICE_EXTENSION newExtension; ! 1133: ! 1134: head = RemoveHeadList(&listHead); ! 1135: ! 1136: currentConfig = CONTAINING_RECORD( ! 1137: head, ! 1138: CONFIG_DATA, ! 1139: SameInterrupt ! 1140: ); ! 1141: ! 1142: if (!IsListEmpty(¤tConfig->SameInterruptStatus)) { ! 1143: ! 1144: // ! 1145: // This is a multiport card, call its intialization. ! 1146: // ! 1147: ! 1148: SerialDump( ! 1149: SERDIAG5, ! 1150: ("SERIAL: Attempting to make %wZ with controller at %x\n" ! 1151: "------- and status at %x a same interrupt sharer multiports\n", ! 1152: ¤tConfig->NtNameForPort,currentConfig->Controller.LowPart, ! 1153: currentConfig->InterruptStatus.LowPart) ! 1154: ); ! 1155: status = SerialInitializeRootMultiPort( ! 1156: DriverObject, ! 1157: currentConfig, ! 1158: &newExtension ! 1159: ); ! 1160: ! 1161: } else { ! 1162: ! 1163: SerialDump( ! 1164: SERDIAG5, ! 1165: ("SERIAL: Attempting to make %wZ with controller at %x\n" ! 1166: "------- A single same interrupt sharer controller.\n", ! 1167: ¤tConfig->NtNameForPort,currentConfig->Controller.LowPart) ! 1168: ); ! 1169: status = SerialInitializeOneController( ! 1170: DriverObject, ! 1171: currentConfig, ! 1172: FALSE, ! 1173: &newExtension ! 1174: ); ! 1175: ! 1176: } ! 1177: ! 1178: SerialDump( ! 1179: SERDIAG5, ! 1180: ("SERIAL: It came back with a same interrupt newExtension of %x\n", ! 1181: rootExtension) ! 1182: ); ! 1183: ! 1184: ! 1185: if (NT_SUCCESS(status)) { ! 1186: ! 1187: PLIST_ENTRY rootTail; ! 1188: PLIST_ENTRY newTail; ! 1189: ! 1190: // ! 1191: // Propagate the isr routine and context ! 1192: // up to the sharing list. ! 1193: // ! 1194: ! 1195: newExtension->TopLevelOurIsr = newExtension->OurIsr; ! 1196: newExtension->TopLevelOurIsrContext = newExtension->OurIsrContext; ! 1197: newExtension->OurIsr = NULL; ! 1198: newExtension->OurIsrContext = NULL; ! 1199: ! 1200: // ! 1201: // Append this top level extension onto the list of ! 1202: // other top level interrupt sharers. ! 1203: // ! 1204: ! 1205: InsertTailList( ! 1206: &rootExtension->TopLevelSharers, ! 1207: &newExtension->TopLevelSharers ! 1208: ); ! 1209: ! 1210: // ! 1211: // Link together the lists of extensions that will ! 1212: // be using the same interrupt object (not necessarily) ! 1213: // the same "interrupt service routine" (actually dispatchers). ! 1214: // ! 1215: ! 1216: rootTail = ! 1217: rootExtension->CommonInterruptObject.Blink; ! 1218: newTail = ! 1219: newExtension->CommonInterruptObject.Blink; ! 1220: ! 1221: rootExtension->CommonInterruptObject.Blink = ! 1222: newTail; ! 1223: newExtension->CommonInterruptObject.Blink = ! 1224: rootTail; ! 1225: rootTail->Flink = ! 1226: &newExtension->CommonInterruptObject; ! 1227: newTail->Flink = ! 1228: &rootExtension->CommonInterruptObject; ! 1229: ! 1230: numberOfSharers++; ! 1231: ! 1232: } ! 1233: ! 1234: } ! 1235: ! 1236: // ! 1237: // All done initializing the other sharers. ! 1238: // ! 1239: // If none of the others actually initialized ! 1240: // the we simply degenerate into the interrupt ! 1241: // handling for the root extension. (This requires ! 1242: // no additional work.) ! 1243: // ! 1244: ! 1245: if (numberOfSharers > 1) { ! 1246: ! 1247: // ! 1248: // Replace the Isr and context for the root ! 1249: // with the pointer to the "sharer" dispatcher ! 1250: // and a pointer to the list of share entries ! 1251: // as context. ! 1252: // ! 1253: ! 1254: SerialDump( ! 1255: SERDIAG5, ! 1256: ("SERIAL: We do have more than one sharer for the interrupt.\n" ! 1257: "------- The controlling extension should be %x\n", ! 1258: rootExtension) ! 1259: ); ! 1260: rootExtension->OurIsr = SerialSharerIsr; ! 1261: rootExtension->OurIsrContext = &rootExtension->TopLevelSharers; ! 1262: ! 1263: } ! 1264: ! 1265: } ! 1266: ! 1267: } ! 1268: ! 1269: } ! 1270: ! 1271: NTSTATUS ! 1272: SerialInitializeRootMultiPort( ! 1273: IN PDRIVER_OBJECT DriverObject, ! 1274: IN PCONFIG_DATA ConfigData, ! 1275: OUT PSERIAL_DEVICE_EXTENSION *DeviceExtension ! 1276: ) ! 1277: ! 1278: /*++ ! 1279: ! 1280: Routine Description: ! 1281: ! 1282: This routine attempts to initialize all the ports on a ! 1283: multiport board and to build a structure so that an ! 1284: isr can dispatch to the particular ports device extension. ! 1285: ! 1286: Arguments: ! 1287: ! 1288: DriverObject - Simply passed on to the controller initialization ! 1289: routine. ! 1290: ! 1291: ConfigData - A linked list of configuration information for all ! 1292: the ports on a multiport card. ! 1293: ! 1294: DeviceExtension - Will point to the first successfully initialized ! 1295: port on the multiport card. ! 1296: ! 1297: Return Value: ! 1298: ! 1299: None. ! 1300: ! 1301: --*/ ! 1302: ! 1303: { ! 1304: ! 1305: PSERIAL_DEVICE_EXTENSION rootExtension = NULL; ! 1306: PCONFIG_DATA originalConfig = ConfigData; ! 1307: PCONFIG_DATA currentConfig = ConfigData; ! 1308: ULONG indexed; ! 1309: ULONG portIndex; ! 1310: LIST_ENTRY listHead; ! 1311: NTSTATUS status; ! 1312: ! 1313: SerialDump( ! 1314: SERDIAG3, ! 1315: ("SERIAL: In SerialInitializeRootMultiPort\n") ! 1316: ); ! 1317: *DeviceExtension = NULL; ! 1318: ! 1319: // ! 1320: // This makes the listhead imbedded in the root config ! 1321: // record a local list head. The old head of the list ! 1322: // (the current config) will no longer be part of the list. ! 1323: // ! 1324: ! 1325: InitializeListHead(&listHead); ! 1326: ! 1327: if (!IsListEmpty(&ConfigData->SameInterruptStatus)) { ! 1328: ! 1329: PLIST_ENTRY old = ConfigData->SameInterruptStatus.Flink; ! 1330: ! 1331: RemoveEntryList(&ConfigData->SameInterruptStatus); ! 1332: InsertTailList( ! 1333: old, ! 1334: &listHead ! 1335: ); ! 1336: ! 1337: } ! 1338: ! 1339: // ! 1340: // The indexed field is valid for all ports on the chain. ! 1341: // ! 1342: ! 1343: indexed = ConfigData->Indexed; ! 1344: SerialDump( ! 1345: SERDIAG5, ! 1346: ("SERIAL: This indexed value for this multiport is: %d\n",indexed) ! 1347: ); ! 1348: ! 1349: // ! 1350: // We first keep trying to initialize one of the ! 1351: // ports on the chain until one succeeds. ! 1352: // ! 1353: ! 1354: while ((!rootExtension) && currentConfig) { ! 1355: ! 1356: portIndex = currentConfig->PortIndex; ! 1357: ! 1358: SerialDump( ! 1359: SERDIAG5, ! 1360: ("SERIAL: Attempting to make %wZ with controller at %x\n" ! 1361: "------- and status at %x a root of multiports\n", ! 1362: ¤tConfig->NtNameForPort,currentConfig->Controller.LowPart, ! 1363: currentConfig->InterruptStatus.LowPart) ! 1364: ); ! 1365: status = SerialInitializeOneController( ! 1366: DriverObject, ! 1367: currentConfig, ! 1368: TRUE, ! 1369: &rootExtension ! 1370: ); ! 1371: SerialDump( ! 1372: SERDIAG5, ! 1373: ("SERIAL: Multiport came back with a same interrupt rootExtension of %x\n", ! 1374: rootExtension) ! 1375: ); ! 1376: ! 1377: if (!NT_SUCCESS(status)) { ! 1378: ! 1379: // ! 1380: // Well that one didn't work. Try the next one. ! 1381: // ! 1382: ! 1383: if (!IsListEmpty(&listHead)) { ! 1384: ! 1385: PLIST_ENTRY head; ! 1386: ! 1387: head = RemoveHeadList(&listHead); ! 1388: ! 1389: currentConfig = CONTAINING_RECORD( ! 1390: head, ! 1391: CONFIG_DATA, ! 1392: SameInterruptStatus ! 1393: ); ! 1394: ! 1395: } else { ! 1396: ! 1397: currentConfig = NULL; ! 1398: rootExtension = NULL; ! 1399: ! 1400: } ! 1401: ! 1402: } ! 1403: ! 1404: } ! 1405: ! 1406: if (rootExtension) { ! 1407: ! 1408: // ! 1409: // Well we have at least one controller. We build a local ! 1410: // dispatch structure. If we end up being able to ! 1411: // intialize another port then we will allocate ! 1412: // the dispatch structure out of pool. If we can't ! 1413: // intialize anymore ports then this degenerates into a ! 1414: // single port case. ! 1415: // ! 1416: ! 1417: ULONG numberOfPorts = 1; ! 1418: SERIAL_MULTIPORT_DISPATCH dispatch; ! 1419: ! 1420: rootExtension->PortOnAMultiportCard = TRUE; ! 1421: ! 1422: RtlZeroMemory( ! 1423: &dispatch, ! 1424: sizeof(SERIAL_MULTIPORT_DISPATCH) ! 1425: ); ! 1426: ! 1427: if (!indexed) { ! 1428: ! 1429: dispatch.UsablePortMask = 1 << (portIndex-1); ! 1430: ! 1431: } ! 1432: ! 1433: dispatch.InterruptStatus = rootExtension->InterruptStatus; ! 1434: ! 1435: dispatch.Extensions[portIndex-1] = rootExtension; ! 1436: ! 1437: while (!IsListEmpty(&listHead)) { ! 1438: ! 1439: PLIST_ENTRY head; ! 1440: PSERIAL_DEVICE_EXTENSION newExtension; ! 1441: ! 1442: head = RemoveHeadList(&listHead); ! 1443: ! 1444: currentConfig = CONTAINING_RECORD( ! 1445: head, ! 1446: CONFIG_DATA, ! 1447: SameInterruptStatus ! 1448: ); ! 1449: ! 1450: portIndex = currentConfig->PortIndex; ! 1451: ! 1452: if (NT_SUCCESS(SerialInitializeOneController( ! 1453: DriverObject, ! 1454: currentConfig, ! 1455: FALSE, ! 1456: &newExtension ! 1457: ))) { ! 1458: ! 1459: numberOfPorts++; ! 1460: newExtension->PortOnAMultiportCard = TRUE; ! 1461: ! 1462: if (!indexed) { ! 1463: ! 1464: dispatch.UsablePortMask |= 1 << (portIndex-1); ! 1465: ! 1466: } ! 1467: ! 1468: dispatch.Extensions[portIndex-1] = newExtension; ! 1469: ! 1470: InsertTailList( ! 1471: &rootExtension->CommonInterruptObject, ! 1472: &newExtension->CommonInterruptObject ! 1473: ); ! 1474: ! 1475: } ! 1476: ! 1477: } ! 1478: ! 1479: // ! 1480: // If the number of ports is still one that means we ! 1481: // couldn't initialize any more extensions. This then ! 1482: // degenerates into a single port card. Note that there ! 1483: // is no work to do in that case, it was set up in ! 1484: // SerialInitializeSingleController. ! 1485: // ! 1486: ! 1487: if (numberOfPorts > 1) { ! 1488: ! 1489: // ! 1490: // Now allocate the dispatch structure out of pool ! 1491: // since it certain that we will actually use it. ! 1492: // ! 1493: ! 1494: rootExtension->OurIsrContext = ExAllocatePool( ! 1495: NonPagedPool, ! 1496: sizeof(SERIAL_MULTIPORT_DISPATCH) ! 1497: ); ! 1498: ! 1499: if (!rootExtension->OurIsrContext) { ! 1500: ! 1501: // ! 1502: // Darn! Couldn't allocate the dispatch structure. ! 1503: // ! 1504: // Seems as though the safest thing to do in ! 1505: // this case is to act as though none of the ports ! 1506: // initialized. Go through and delete all of the ! 1507: // devices that were initialized. ! 1508: // ! 1509: // This should be fairly safe since the initialize controller ! 1510: // code completely disables the port from interrupting. ! 1511: // ! 1512: ! 1513: ULONG i; ! 1514: ! 1515: SerialDump( ! 1516: SERERRORS, ! 1517: ("SERIAL: Couldn't allocate memory for %wZ\n" ! 1518: "------- multiport dispatch structure" ! 1519: "------- deleting all associated devices", ! 1520: &rootExtension->DeviceName) ! 1521: ); ! 1522: ! 1523: // ! 1524: // We couldn't allocate memory for it, hopefully ! 1525: // the logger can make some headway. ! 1526: // ! 1527: ! 1528: SerialLogError( ! 1529: rootExtension->DeviceObject->DriverObject, ! 1530: rootExtension->DeviceObject, ! 1531: rootExtension->OriginalController, ! 1532: SerialPhysicalZero, ! 1533: 0, ! 1534: 0, ! 1535: 0, ! 1536: 2, ! 1537: STATUS_SUCCESS, ! 1538: SERIAL_INSUFFICIENT_RESOURCES, ! 1539: 0, ! 1540: NULL, ! 1541: 0, ! 1542: NULL ! 1543: ); ! 1544: ! 1545: for ( ! 1546: i = 0; ! 1547: numberOfPorts; ! 1548: i++ ! 1549: ) { ! 1550: ! 1551: if (dispatch.Extensions[i]) { ! 1552: ! 1553: SerialCleanupDevice(dispatch.Extensions[i]); ! 1554: IoDeleteDevice( ! 1555: dispatch.Extensions[i]->DeviceObject ! 1556: ); ! 1557: numberOfPorts--; ! 1558: ! 1559: } ! 1560: ! 1561: } ! 1562: ! 1563: return STATUS_INSUFFICIENT_RESOURCES; ! 1564: ! 1565: } else { ! 1566: ! 1567: ULONG i; ! 1568: PSERIAL_MULTIPORT_DISPATCH allocatedDispatch = ! 1569: rootExtension->OurIsrContext; ! 1570: ! 1571: // ! 1572: // Go throught the list of extensions and NULL ! 1573: // their pointers to the isr. The only extension ! 1574: // that will truely have an isr is the root. ! 1575: // ! 1576: ! 1577: allocatedDispatch->UsablePortMask = dispatch.UsablePortMask; ! 1578: allocatedDispatch->InterruptStatus = dispatch.InterruptStatus; ! 1579: ! 1580: for ( ! 1581: i = 0; ! 1582: i < SERIAL_MAX_PORTS_NONINDEXED; ! 1583: i++ ! 1584: ) { ! 1585: ! 1586: allocatedDispatch->Extensions[i] = dispatch.Extensions[i]; ! 1587: ! 1588: if (dispatch.Extensions[i]) { ! 1589: dispatch.Extensions[i]->OurIsr = NULL; ! 1590: } ! 1591: ! 1592: } ! 1593: ! 1594: if (indexed) { ! 1595: ! 1596: rootExtension->OurIsr = SerialIndexedMultiportIsr; ! 1597: ! 1598: } else { ! 1599: ! 1600: rootExtension->OurIsr = SerialBitMappedMultiportIsr; ! 1601: ! 1602: } ! 1603: ! 1604: } ! 1605: ! 1606: } ! 1607: ! 1608: *DeviceExtension = rootExtension; ! 1609: return STATUS_SUCCESS; ! 1610: ! 1611: } else { ! 1612: ! 1613: return STATUS_UNSUCCESSFUL; ! 1614: ! 1615: } ! 1616: ! 1617: } ! 1618: ! 1619: NTSTATUS ! 1620: SerialInitializeOneController( ! 1621: IN PDRIVER_OBJECT DriverObject, ! 1622: IN PCONFIG_DATA ConfigData, ! 1623: IN BOOLEAN MapInterruptStatus, ! 1624: OUT PSERIAL_DEVICE_EXTENSION *Extension ! 1625: ) ! 1626: ! 1627: /*++ ! 1628: ! 1629: Routine Description: ! 1630: ! 1631: This routine will call the real port initializatio code. ! 1632: If all was successful, it will save off in the extension ! 1633: the isr that should be used as well as a pointer to ! 1634: the extension itself. ! 1635: ! 1636: This is the only routine responsible for deleting the ! 1637: configuration information subsequent to getting it all ! 1638: from the registry. ! 1639: ! 1640: Arguments: ! 1641: ! 1642: DriverObject - Simply passed on to the controller initialization ! 1643: routine. ! 1644: ! 1645: ConfigData - Pointer to a record for a single port. ! 1646: ! 1647: MapInterruptStatus - Simply passed on to the controller initialization ! 1648: routine. ! 1649: ! 1650: Extension - Points to the device extension of the successfully ! 1651: initialized controller. ! 1652: ! 1653: Return Value: ! 1654: ! 1655: Status returned from the controller initialization routine. ! 1656: ! 1657: --*/ ! 1658: ! 1659: { ! 1660: ! 1661: NTSTATUS status; ! 1662: ! 1663: status = SerialInitializeController( ! 1664: DriverObject, ! 1665: ConfigData, ! 1666: MapInterruptStatus, ! 1667: Extension ! 1668: ); ! 1669: ! 1670: if (NT_SUCCESS(status)) { ! 1671: ! 1672: // ! 1673: // We successfully initialized the single controller. ! 1674: // Stick the isr routine and the parameter for it ! 1675: // back into the extension. ! 1676: // ! 1677: ! 1678: (*Extension)->OurIsr = SerialISR; ! 1679: (*Extension)->OurIsrContext = *Extension; ! 1680: ! 1681: } else { ! 1682: ! 1683: *Extension = NULL; ! 1684: ! 1685: } ! 1686: ! 1687: return status; ! 1688: ! 1689: } ! 1690: ! 1691: NTSTATUS ! 1692: SerialInitializeController( ! 1693: IN PDRIVER_OBJECT DriverObject, ! 1694: IN PCONFIG_DATA ConfigData, ! 1695: IN BOOLEAN MapInterruptStatus, ! 1696: OUT PSERIAL_DEVICE_EXTENSION *DeviceExtension ! 1697: ) ! 1698: ! 1699: /*++ ! 1700: ! 1701: Routine Description: ! 1702: ! 1703: Really too many things to mention here. In general, it forms ! 1704: and sets up names, creates the device, initializes kernel ! 1705: synchronization structures, allocates the typeahead buffer, ! 1706: sets up defaults, etc. ! 1707: ! 1708: Arguments: ! 1709: ! 1710: DriverObject - Just used to create the device object. ! 1711: ! 1712: ConfigData - Pointer to a record for a single port. ! 1713: ! 1714: NOTE: This routine will deallocate the config data. ! 1715: ! 1716: MapInterruptStatus - If true, we will attempt to map the ! 1717: interrupt status register associated ! 1718: with this port.. ! 1719: ! 1720: DeviceExtension - Points to the device extension of the successfully ! 1721: initialized controller. ! 1722: ! 1723: Return Value: ! 1724: ! 1725: STATUS_SUCCCESS if everything went ok. A !NT_SUCCESS status ! 1726: otherwise. ! 1727: ! 1728: --*/ ! 1729: ! 1730: { ! 1731: ! 1732: // ! 1733: // This will hold the string that we need to use to describe ! 1734: // the name of the device to the IO system. ! 1735: // ! 1736: UNICODE_STRING uniNameString; ! 1737: ! 1738: // ! 1739: // Holds the NT Status that is returned from each call to the ! 1740: // kernel and executive. ! 1741: // ! 1742: NTSTATUS status = STATUS_SUCCESS; ! 1743: ! 1744: // ! 1745: // Points to the device object (not the extension) created ! 1746: // for this device. ! 1747: // ! 1748: PDEVICE_OBJECT deviceObject; ! 1749: ! 1750: // ! 1751: // Points to the device extension for the device object ! 1752: // (see above) created for the device we are initializing. ! 1753: // ! 1754: PSERIAL_DEVICE_EXTENSION extension = NULL; ! 1755: ! 1756: // ! 1757: // Indicates that we successfully reported the resources ! 1758: // used by this device. ! 1759: // ! 1760: BOOLEAN reportedResources = FALSE; ! 1761: ! 1762: // ! 1763: // Indicates that a conflict was detected for resources ! 1764: // used by this device. ! 1765: // ! 1766: BOOLEAN conflictDetected = FALSE; ! 1767: ! 1768: SerialDump( ! 1769: SERDIAG1, ! 1770: ("SERIAL: Initializing for configuration record of %wZ\n", ! 1771: &ConfigData->NtNameForPort) ! 1772: ); ! 1773: if ((*KdComPortInUse) == ! 1774: ! 1775: ((PUCHAR)(ConfigData->Controller.LowPart))) { ! 1776: SerialDump( ! 1777: SERERRORS, ! 1778: ("SERIAL: Kernel debugger is using port at address %x\n" ! 1779: "------ Serial driver will not load port %wZ\n", ! 1780: *KdComPortInUse,&ConfigData->SymbolicLinkName) ! 1781: ); ! 1782: ! 1783: SerialLogError( ! 1784: DriverObject, ! 1785: NULL, ! 1786: ConfigData->Controller, ! 1787: SerialPhysicalZero, ! 1788: 0, ! 1789: 0, ! 1790: 0, ! 1791: 3, ! 1792: STATUS_SUCCESS, ! 1793: SERIAL_KERNEL_DEBUGGER_ACTIVE, ! 1794: ConfigData->SymbolicLinkName.Length+sizeof(WCHAR), ! 1795: ConfigData->SymbolicLinkName.Buffer, ! 1796: 0, ! 1797: NULL ! 1798: ); ! 1799: ! 1800: ExFreePool(ConfigData->ObjectDirectory.Buffer); ! 1801: ExFreePool(ConfigData->NtNameForPort.Buffer); ! 1802: ExFreePool(ConfigData->SymbolicLinkName.Buffer); ! 1803: ExFreePool(ConfigData); ! 1804: return STATUS_INSUFFICIENT_RESOURCES; ! 1805: ! 1806: } ! 1807: ! 1808: // ! 1809: // Form a name like \Device\Serial0. ! 1810: // ! 1811: // First we allocate space for the name. ! 1812: // ! 1813: ! 1814: RtlInitUnicodeString( ! 1815: &uniNameString, ! 1816: NULL ! 1817: ); ! 1818: ! 1819: uniNameString.MaximumLength = sizeof(L"\\Device\\") + ! 1820: ConfigData->NtNameForPort.Length+sizeof(WCHAR); ! 1821: uniNameString.Buffer = ExAllocatePool( ! 1822: PagedPool, ! 1823: uniNameString.MaximumLength ! 1824: ); ! 1825: ! 1826: // ! 1827: // The only reason the above could have failed is if ! 1828: // there wasn't enough system memory to form the UNICODE ! 1829: // string. ! 1830: // ! 1831: ! 1832: if (!uniNameString.Buffer) { ! 1833: ! 1834: SerialDump( ! 1835: SERERRORS, ! 1836: ("SERIAL: Could not form Unicode name string for %wZ\n", ! 1837: &ConfigData->NtNameForPort) ! 1838: ); ! 1839: SerialLogError( ! 1840: DriverObject, ! 1841: NULL, ! 1842: ConfigData->Controller, ! 1843: SerialPhysicalZero, ! 1844: 0, ! 1845: 0, ! 1846: 0, ! 1847: 4, ! 1848: STATUS_SUCCESS, ! 1849: SERIAL_INSUFFICIENT_RESOURCES, ! 1850: 0, ! 1851: NULL, ! 1852: 0, ! 1853: NULL ! 1854: ); ! 1855: ExFreePool(ConfigData->ObjectDirectory.Buffer); ! 1856: ExFreePool(ConfigData->NtNameForPort.Buffer); ! 1857: ExFreePool(ConfigData->SymbolicLinkName.Buffer); ! 1858: ExFreePool(ConfigData); ! 1859: return STATUS_INSUFFICIENT_RESOURCES; ! 1860: ! 1861: } ! 1862: ! 1863: // ! 1864: // Actually form the Name. ! 1865: // ! 1866: ! 1867: RtlZeroMemory( ! 1868: uniNameString.Buffer, ! 1869: uniNameString.MaximumLength ! 1870: ); ! 1871: ! 1872: RtlAppendUnicodeToString( ! 1873: &uniNameString, ! 1874: L"\\Device\\" ! 1875: ); ! 1876: ! 1877: RtlAppendUnicodeStringToString( ! 1878: &uniNameString, ! 1879: &ConfigData->NtNameForPort ! 1880: ); ! 1881: ! 1882: // ! 1883: // Create the device object for this device. ! 1884: // ! 1885: ! 1886: status = IoCreateDevice( ! 1887: DriverObject, ! 1888: sizeof(SERIAL_DEVICE_EXTENSION), ! 1889: &uniNameString, ! 1890: FILE_DEVICE_SERIAL_PORT, ! 1891: 0, ! 1892: TRUE, ! 1893: &deviceObject ! 1894: ); ! 1895: ! 1896: // ! 1897: // If we couldn't create the device object, then there ! 1898: // is no point in going on. ! 1899: // ! 1900: ! 1901: if (!NT_SUCCESS(status)) { ! 1902: ! 1903: SerialDump( ! 1904: SERERRORS, ! 1905: ("SERIAL: Could not create a device for %wZ\n", ! 1906: &ConfigData->NtNameForPort) ! 1907: ); ! 1908: SerialLogError( ! 1909: DriverObject, ! 1910: NULL, ! 1911: ConfigData->Controller, ! 1912: SerialPhysicalZero, ! 1913: 0, ! 1914: 0, ! 1915: 0, ! 1916: 5, ! 1917: status, ! 1918: SERIAL_INSUFFICIENT_RESOURCES, ! 1919: 0, ! 1920: NULL, ! 1921: 0, ! 1922: NULL ! 1923: ); ! 1924: ExFreePool(ConfigData->ObjectDirectory.Buffer); ! 1925: ExFreePool(ConfigData->NtNameForPort.Buffer); ! 1926: ExFreePool(ConfigData->SymbolicLinkName.Buffer); ! 1927: ExFreePool(ConfigData); ! 1928: ExFreePool(uniNameString.Buffer); ! 1929: return STATUS_INSUFFICIENT_RESOURCES; ! 1930: ! 1931: } ! 1932: ! 1933: // ! 1934: // The device object has a pointer to an area of non-paged ! 1935: // pool allocated for this device. This will be the device ! 1936: // extension. ! 1937: // ! 1938: ! 1939: extension = deviceObject->DeviceExtension; ! 1940: ! 1941: // ! 1942: // Zero all of the memory associated with the device ! 1943: // extension. ! 1944: // ! 1945: ! 1946: RtlZeroMemory( ! 1947: extension, ! 1948: sizeof(SERIAL_DEVICE_EXTENSION) ! 1949: ); ! 1950: ! 1951: // ! 1952: // Propagate that it is a jensen. ! 1953: // ! 1954: ! 1955: extension->Jensen = ConfigData->Jensen; ! 1956: ! 1957: // ! 1958: // So far, we don't know if this extension will be ! 1959: // shareing it's interrupt object with any other serial ! 1960: // port. ! 1961: // ! 1962: ! 1963: InitializeListHead(&extension->TopLevelSharers); ! 1964: InitializeListHead(&extension->CommonInterruptObject); ! 1965: ! 1966: // ! 1967: // Save off our name. ! 1968: // ! 1969: ! 1970: RtlInitUnicodeString( ! 1971: &extension->DeviceName, ! 1972: NULL ! 1973: ); ! 1974: ! 1975: extension->DeviceName.Length = uniNameString.Length; ! 1976: extension->DeviceName.MaximumLength = uniNameString.MaximumLength; ! 1977: extension->DeviceName.Buffer = uniNameString.Buffer; ! 1978: ! 1979: // ! 1980: // Just initialize the names so that we don't try ! 1981: // to "clean" them up if we cant intialize the ! 1982: // controller all the way. ! 1983: // ! 1984: ! 1985: RtlInitUnicodeString( ! 1986: &extension->ObjectDirectory, ! 1987: NULL ! 1988: ); ! 1989: RtlInitUnicodeString( ! 1990: &extension->NtNameForPort, ! 1991: NULL ! 1992: ); ! 1993: RtlInitUnicodeString( ! 1994: &extension->SymbolicLinkName, ! 1995: NULL ! 1996: ); ! 1997: ! 1998: // ! 1999: // Initialize the list heads for the read, write, and mask queues. ! 2000: // ! 2001: // These lists will hold all of the queued IRP's for the device. ! 2002: // ! 2003: ! 2004: InitializeListHead(&extension->ReadQueue); ! 2005: InitializeListHead(&extension->WriteQueue); ! 2006: InitializeListHead(&extension->MaskQueue); ! 2007: InitializeListHead(&extension->PurgeQueue); ! 2008: ! 2009: // ! 2010: // Initialize the spinlock associated with fields read (& set) ! 2011: // by IO Control functions. ! 2012: // ! 2013: ! 2014: KeInitializeSpinLock(&extension->ControlLock); ! 2015: ! 2016: // ! 2017: // Initialize the timers used to timeout operations. ! 2018: // ! 2019: ! 2020: KeInitializeTimer(&extension->ReadRequestTotalTimer); ! 2021: KeInitializeTimer(&extension->ReadRequestIntervalTimer); ! 2022: KeInitializeTimer(&extension->WriteRequestTotalTimer); ! 2023: KeInitializeTimer(&extension->ImmediateTotalTimer); ! 2024: KeInitializeTimer(&extension->XoffCountTimer); ! 2025: KeInitializeTimer(&extension->LowerRTSTimer); ! 2026: ! 2027: // ! 2028: // Intialialize the dpcs that will be used to complete ! 2029: // or timeout various IO operations. ! 2030: // ! 2031: ! 2032: KeInitializeDpc( ! 2033: &extension->CompleteWriteDpc, ! 2034: SerialCompleteWrite, ! 2035: extension ! 2036: ); ! 2037: ! 2038: KeInitializeDpc( ! 2039: &extension->CompleteReadDpc, ! 2040: SerialCompleteRead, ! 2041: extension ! 2042: ); ! 2043: ! 2044: KeInitializeDpc( ! 2045: &extension->TotalReadTimeoutDpc, ! 2046: SerialReadTimeout, ! 2047: extension ! 2048: ); ! 2049: ! 2050: KeInitializeDpc( ! 2051: &extension->IntervalReadTimeoutDpc, ! 2052: SerialIntervalReadTimeout, ! 2053: extension ! 2054: ); ! 2055: ! 2056: KeInitializeDpc( ! 2057: &extension->TotalWriteTimeoutDpc, ! 2058: SerialWriteTimeout, ! 2059: extension ! 2060: ); ! 2061: ! 2062: KeInitializeDpc( ! 2063: &extension->CommErrorDpc, ! 2064: SerialCommError, ! 2065: extension ! 2066: ); ! 2067: ! 2068: KeInitializeDpc( ! 2069: &extension->CompleteImmediateDpc, ! 2070: SerialCompleteImmediate, ! 2071: extension ! 2072: ); ! 2073: ! 2074: KeInitializeDpc( ! 2075: &extension->TotalImmediateTimeoutDpc, ! 2076: SerialTimeoutImmediate, ! 2077: extension ! 2078: ); ! 2079: ! 2080: KeInitializeDpc( ! 2081: &extension->CommWaitDpc, ! 2082: SerialCompleteWait, ! 2083: extension ! 2084: ); ! 2085: ! 2086: KeInitializeDpc( ! 2087: &extension->XoffCountTimeoutDpc, ! 2088: SerialTimeoutXoff, ! 2089: extension ! 2090: ); ! 2091: ! 2092: KeInitializeDpc( ! 2093: &extension->XoffCountCompleteDpc, ! 2094: SerialCompleteXoff, ! 2095: extension ! 2096: ); ! 2097: ! 2098: KeInitializeDpc( ! 2099: &extension->StartTimerLowerRTSDpc, ! 2100: SerialStartTimerLowerRTS, ! 2101: extension ! 2102: ); ! 2103: ! 2104: KeInitializeDpc( ! 2105: &extension->PerhapsLowerRTSDpc, ! 2106: SerialInvokePerhapsLowerRTS, ! 2107: extension ! 2108: ); ! 2109: ! 2110: if (!((ConfigData->ClockRate == 1843200) || ! 2111: (ConfigData->ClockRate == 3072000) || ! 2112: (ConfigData->ClockRate == 4233600) || ! 2113: (ConfigData->ClockRate == 8000000))) { ! 2114: ! 2115: SerialLogError( ! 2116: extension->DeviceObject->DriverObject, ! 2117: extension->DeviceObject, ! 2118: ConfigData->Controller, ! 2119: SerialPhysicalZero, ! 2120: 0, ! 2121: 0, ! 2122: 0, ! 2123: 6, ! 2124: STATUS_SUCCESS, ! 2125: SERIAL_UNSUPPORTED_CLOCK_RATE, ! 2126: ConfigData->SymbolicLinkName.Length+sizeof(WCHAR), ! 2127: ConfigData->SymbolicLinkName.Buffer, ! 2128: 0, ! 2129: NULL ! 2130: ); ! 2131: SerialDump( ! 2132: SERERRORS, ! 2133: ("SERIAL: Invalid clock rate specified for %wZ\n", ! 2134: &ConfigData->NtNameForPort) ! 2135: ); ! 2136: status = STATUS_SERIAL_NO_DEVICE_INITED; ! 2137: goto ExtensionCleanup; ! 2138: ! 2139: } ! 2140: ! 2141: // ! 2142: // Save the value of clock input to the part. We use this to calculate ! 2143: // the divisor latch value. The value is in Hertz. ! 2144: // ! 2145: ! 2146: extension->ClockRate = ConfigData->ClockRate; ! 2147: ! 2148: // ! 2149: // Get a "back pointer" to the device object and specify ! 2150: // that this driver only supports buffered IO. This basically ! 2151: // means that the IO system copies the users data to and from ! 2152: // system supplied buffers. ! 2153: // ! 2154: ! 2155: extension->DeviceObject = deviceObject; ! 2156: deviceObject->Flags |= DO_BUFFERED_IO; ! 2157: ! 2158: // ! 2159: // Map the memory for the control registers for the serial device ! 2160: // into virtual memory. ! 2161: // ! 2162: ! 2163: extension->Controller = SerialGetMappedAddress( ! 2164: ConfigData->InterfaceType, ! 2165: ConfigData->BusNumber, ! 2166: ConfigData->Controller, ! 2167: ConfigData->SpanOfController, ! 2168: (BOOLEAN)ConfigData->AddressSpace, ! 2169: &extension->UnMapRegisters ! 2170: ); ! 2171: ! 2172: ! 2173: if (!extension->Controller) { ! 2174: ! 2175: SerialLogError( ! 2176: extension->DeviceObject->DriverObject, ! 2177: extension->DeviceObject, ! 2178: ConfigData->Controller, ! 2179: SerialPhysicalZero, ! 2180: 0, ! 2181: 0, ! 2182: 0, ! 2183: 7, ! 2184: STATUS_SUCCESS, ! 2185: SERIAL_REGISTERS_NOT_MAPPED, ! 2186: ConfigData->SymbolicLinkName.Length+sizeof(WCHAR), ! 2187: ConfigData->SymbolicLinkName.Buffer, ! 2188: 0, ! 2189: NULL ! 2190: ); ! 2191: SerialDump( ! 2192: SERERRORS, ! 2193: ("SERIAL: Could not map memory for device registers for %wZ\n", ! 2194: &ConfigData->NtNameForPort) ! 2195: ); ! 2196: extension->UnMapRegisters = FALSE; ! 2197: status = STATUS_NONE_MAPPED; ! 2198: goto ExtensionCleanup; ! 2199: ! 2200: } ! 2201: ! 2202: extension->AddressSpace = ConfigData->AddressSpace; ! 2203: extension->OriginalController = ConfigData->Controller; ! 2204: extension->SpanOfController = ConfigData->SpanOfController; ! 2205: ! 2206: // ! 2207: // if we were requested to map the interrupt status do so. ! 2208: // ! 2209: ! 2210: if (MapInterruptStatus) { ! 2211: ! 2212: extension->InterruptStatus = SerialGetMappedAddress( ! 2213: ConfigData->InterfaceType, ! 2214: ConfigData->BusNumber, ! 2215: ConfigData->InterruptStatus, ! 2216: ConfigData->SpanOfInterruptStatus, ! 2217: (BOOLEAN)ConfigData->AddressSpace, ! 2218: &extension->UnMapStatus ! 2219: ); ! 2220: ! 2221: ! 2222: if (!extension->InterruptStatus) { ! 2223: ! 2224: SerialLogError( ! 2225: extension->DeviceObject->DriverObject, ! 2226: extension->DeviceObject, ! 2227: ConfigData->Controller, ! 2228: SerialPhysicalZero, ! 2229: 0, ! 2230: 0, ! 2231: 0, ! 2232: 8, ! 2233: STATUS_SUCCESS, ! 2234: SERIAL_REGISTERS_NOT_MAPPED, ! 2235: ConfigData->SymbolicLinkName.Length+sizeof(WCHAR), ! 2236: ConfigData->SymbolicLinkName.Buffer, ! 2237: 0, ! 2238: NULL ! 2239: ); ! 2240: SerialDump( ! 2241: SERERRORS, ! 2242: ("SERIAL: Could not map memory for interrupt status for %wZ\n", ! 2243: &ConfigData->NtNameForPort) ! 2244: ); ! 2245: extension->UnMapRegisters = FALSE; ! 2246: status = STATUS_NONE_MAPPED; ! 2247: goto ExtensionCleanup; ! 2248: ! 2249: } ! 2250: ! 2251: extension->OriginalInterruptStatus = ConfigData->InterruptStatus; ! 2252: extension->SpanOfInterruptStatus = ConfigData->SpanOfInterruptStatus; ! 2253: ! 2254: } ! 2255: ! 2256: // ! 2257: // For now, assume that unless we are on a MicroChannel ! 2258: // machine the interrupt isn't shareable. ! 2259: // ! 2260: // BUG BUG Is there some EISA data out there that will ! 2261: // BUG BUG tell us whether the card is a true EISA card? ! 2262: // ! 2263: ! 2264: if (ConfigData->InterfaceType == MicroChannel) { ! 2265: ! 2266: extension->InterruptShareable = TRUE; ! 2267: ! 2268: } else { ! 2269: ! 2270: extension->InterruptShareable = FALSE; ! 2271: ! 2272: } ! 2273: ! 2274: // ! 2275: // Save off the interface type and the bus number. ! 2276: // ! 2277: ! 2278: extension->InterfaceType = ConfigData->InterfaceType; ! 2279: extension->BusNumber = ConfigData->BusNumber; ! 2280: ! 2281: // ! 2282: // From the Hal, get the interrupt vector and level. ! 2283: // ! 2284: ! 2285: extension->InterruptMode = ConfigData->InterruptMode; ! 2286: extension->OriginalIrql = ConfigData->OriginalIrql; ! 2287: extension->OriginalVector = ConfigData->OriginalVector; ! 2288: extension->Vector = HalGetInterruptVector( ! 2289: ConfigData->InterfaceType, ! 2290: ConfigData->BusNumber, ! 2291: ConfigData->OriginalIrql, ! 2292: ConfigData->OriginalVector, ! 2293: &extension->Irql, ! 2294: &extension->ProcessorAffinity ! 2295: ); ! 2296: ! 2297: // ! 2298: // Report it's resources. We do this now because we are just ! 2299: // about to touch the resources for the first time. ! 2300: // ! 2301: ! 2302: SerialReportResourcesDevice( ! 2303: extension, ! 2304: &conflictDetected ! 2305: ); ! 2306: ! 2307: if (conflictDetected) { ! 2308: ! 2309: SerialDump( ! 2310: SERERRORS, ! 2311: ("SERIAL: Reporting resources for %wZ with extension %x\n" ! 2312: "------- detected a conflict\n", ! 2313: &extension->NtNameForPort,extension) ! 2314: ); ! 2315: SerialLogError( ! 2316: extension->DeviceObject->DriverObject, ! 2317: extension->DeviceObject, ! 2318: ConfigData->Controller, ! 2319: SerialPhysicalZero, ! 2320: 0, ! 2321: 0, ! 2322: 0, ! 2323: 9, ! 2324: STATUS_SUCCESS, ! 2325: SERIAL_RESOURCE_CONFLICT, ! 2326: ConfigData->SymbolicLinkName.Length+sizeof(WCHAR), ! 2327: ConfigData->SymbolicLinkName.Buffer, ! 2328: 0, ! 2329: NULL ! 2330: ); ! 2331: ! 2332: // ! 2333: // This status won't propagate far. ! 2334: // ! 2335: ! 2336: status = STATUS_INSUFFICIENT_RESOURCES; ! 2337: goto ExtensionCleanup; ! 2338: ! 2339: } ! 2340: ! 2341: reportedResources = TRUE; ! 2342: ! 2343: // ! 2344: // Before we test whether the port exists (which will enable the FIFO) ! 2345: // convert the rx trigger value to what should be used in the register. ! 2346: // ! 2347: // If a bogus value was given - crank them down to 1. ! 2348: // ! 2349: ! 2350: switch (ConfigData->RxFIFO) { ! 2351: ! 2352: case 1: ! 2353: ! 2354: extension->RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER; ! 2355: break; ! 2356: ! 2357: case 4: ! 2358: ! 2359: extension->RxFifoTrigger = SERIAL_4_BYTE_HIGH_WATER; ! 2360: break; ! 2361: ! 2362: case 8: ! 2363: ! 2364: extension->RxFifoTrigger = SERIAL_8_BYTE_HIGH_WATER; ! 2365: break; ! 2366: ! 2367: case 14: ! 2368: ! 2369: extension->RxFifoTrigger = SERIAL_14_BYTE_HIGH_WATER; ! 2370: break; ! 2371: ! 2372: default: ! 2373: ! 2374: extension->RxFifoTrigger = SERIAL_1_BYTE_HIGH_WATER; ! 2375: break; ! 2376: ! 2377: } ! 2378: ! 2379: if (!SerialDoesPortExist( ! 2380: extension, ! 2381: &ConfigData->SymbolicLinkName, ! 2382: ConfigData->ForceFifoEnable ! 2383: )) { ! 2384: ! 2385: // ! 2386: // We couldn't verify that there was actually a ! 2387: // port. No need to log an error as the port exist ! 2388: // code will log exactly why. ! 2389: // ! 2390: ! 2391: SerialDump( ! 2392: SERERRORS, ! 2393: ("SERIAL: Does Port exist test failed for %wZ\n", ! 2394: &ConfigData->NtNameForPort) ! 2395: ); ! 2396: status = STATUS_NO_SUCH_DEVICE; ! 2397: goto ExtensionCleanup; ! 2398: ! 2399: } ! 2400: ! 2401: // ! 2402: // If the user requested that we disable the port, then ! 2403: // do it now. Log the fact that the port has been disabled. ! 2404: // ! 2405: ! 2406: if (ConfigData->DisablePort) { ! 2407: ! 2408: SerialDump( ! 2409: SERERRORS, ! 2410: ("SERIAL: disabled port %wZ as requested in configuration\n", ! 2411: &ConfigData->NtNameForPort) ! 2412: ); ! 2413: status = STATUS_NO_SUCH_DEVICE; ! 2414: SerialLogError( ! 2415: extension->DeviceObject->DriverObject, ! 2416: extension->DeviceObject, ! 2417: ConfigData->Controller, ! 2418: SerialPhysicalZero, ! 2419: 0, ! 2420: 0, ! 2421: 0, ! 2422: 57, ! 2423: STATUS_SUCCESS, ! 2424: SERIAL_DISABLED_PORT, ! 2425: ConfigData->SymbolicLinkName.Length+sizeof(WCHAR), ! 2426: ConfigData->SymbolicLinkName.Buffer, ! 2427: 0, ! 2428: NULL ! 2429: ); ! 2430: goto ExtensionCleanup; ! 2431: ! 2432: } ! 2433: ! 2434: ! 2435: ! 2436: // ! 2437: // Set up the default device control fields. ! 2438: // Note that if the values are changed after ! 2439: // the file is open, they do NOT revert back ! 2440: // to the old value at file close. ! 2441: // ! 2442: ! 2443: extension->SpecialChars.XonChar = SERIAL_DEF_XON; ! 2444: extension->SpecialChars.XoffChar = SERIAL_DEF_XOFF; ! 2445: extension->HandFlow.ControlHandShake = SERIAL_DTR_CONTROL; ! 2446: ! 2447: extension->HandFlow.FlowReplace = SERIAL_RTS_CONTROL; ! 2448: ! 2449: // ! 2450: // Default Line control protocol. 7E1 ! 2451: // ! 2452: // Seven data bits. ! 2453: // Even parity. ! 2454: // 1 Stop bits. ! 2455: // ! 2456: ! 2457: extension->LineControl = SERIAL_7_DATA | ! 2458: SERIAL_EVEN_PARITY | ! 2459: SERIAL_NONE_PARITY; ! 2460: ! 2461: extension->ValidDataMask = 0x7f; ! 2462: extension->CurrentBaud = 1200; ! 2463: ! 2464: ! 2465: // ! 2466: // We set up the default xon/xoff limits. ! 2467: // ! 2468: ! 2469: extension->HandFlow.XoffLimit = extension->BufferSize >> 3; ! 2470: extension->HandFlow.XonLimit = extension->BufferSize >> 1; ! 2471: ! 2472: extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+ ! 2473: (extension->BufferSize>>4)); ! 2474: ! 2475: SerialDump( ! 2476: SERDIAG1, ! 2477: ("SERIAL: The default interrupt read buffer size is: %d\n" ! 2478: "------ The XoffLimit is : %d\n" ! 2479: "------ The XonLimit is : %d\n" ! 2480: "------ The pt 8 size is : %d\n", ! 2481: extension->BufferSize, ! 2482: extension->HandFlow.XoffLimit, ! 2483: extension->HandFlow.XonLimit, ! 2484: extension->BufferSizePt8) ! 2485: ); ! 2486: ! 2487: // ! 2488: // Go through all the "named" baud rates to find out which ones ! 2489: // can be supported with this port. ! 2490: // ! 2491: ! 2492: extension->SupportedBauds = SERIAL_BAUD_USER; ! 2493: ! 2494: { ! 2495: ! 2496: SHORT junk; ! 2497: ! 2498: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2499: extension->ClockRate, ! 2500: (LONG)75, ! 2501: &junk ! 2502: ))) { ! 2503: ! 2504: extension->SupportedBauds |= SERIAL_BAUD_075; ! 2505: ! 2506: } ! 2507: ! 2508: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2509: extension->ClockRate, ! 2510: (LONG)110, ! 2511: &junk ! 2512: ))) { ! 2513: ! 2514: extension->SupportedBauds |= SERIAL_BAUD_110; ! 2515: ! 2516: } ! 2517: ! 2518: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2519: extension->ClockRate, ! 2520: (LONG)135, ! 2521: &junk ! 2522: ))) { ! 2523: ! 2524: extension->SupportedBauds |= SERIAL_BAUD_134_5; ! 2525: ! 2526: } ! 2527: ! 2528: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2529: extension->ClockRate, ! 2530: (LONG)150, ! 2531: &junk ! 2532: ))) { ! 2533: ! 2534: extension->SupportedBauds |= SERIAL_BAUD_150; ! 2535: ! 2536: } ! 2537: ! 2538: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2539: extension->ClockRate, ! 2540: (LONG)300, ! 2541: &junk ! 2542: ))) { ! 2543: ! 2544: extension->SupportedBauds |= SERIAL_BAUD_300; ! 2545: ! 2546: } ! 2547: ! 2548: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2549: extension->ClockRate, ! 2550: (LONG)600, ! 2551: &junk ! 2552: ))) { ! 2553: ! 2554: extension->SupportedBauds |= SERIAL_BAUD_600; ! 2555: ! 2556: } ! 2557: ! 2558: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2559: extension->ClockRate, ! 2560: (LONG)1200, ! 2561: &junk ! 2562: ))) { ! 2563: ! 2564: extension->SupportedBauds |= SERIAL_BAUD_1200; ! 2565: ! 2566: } ! 2567: ! 2568: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2569: extension->ClockRate, ! 2570: (LONG)1800, ! 2571: &junk ! 2572: ))) { ! 2573: ! 2574: extension->SupportedBauds |= SERIAL_BAUD_1800; ! 2575: ! 2576: } ! 2577: ! 2578: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2579: extension->ClockRate, ! 2580: (LONG)2400, ! 2581: &junk ! 2582: ))) { ! 2583: ! 2584: extension->SupportedBauds |= SERIAL_BAUD_2400; ! 2585: ! 2586: } ! 2587: ! 2588: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2589: extension->ClockRate, ! 2590: (LONG)4800, ! 2591: &junk ! 2592: ))) { ! 2593: ! 2594: extension->SupportedBauds |= SERIAL_BAUD_4800; ! 2595: ! 2596: } ! 2597: ! 2598: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2599: extension->ClockRate, ! 2600: (LONG)7200, ! 2601: &junk ! 2602: ))) { ! 2603: ! 2604: extension->SupportedBauds |= SERIAL_BAUD_7200; ! 2605: ! 2606: } ! 2607: ! 2608: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2609: extension->ClockRate, ! 2610: (LONG)9600, ! 2611: &junk ! 2612: ))) { ! 2613: ! 2614: extension->SupportedBauds |= SERIAL_BAUD_9600; ! 2615: ! 2616: } ! 2617: ! 2618: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2619: extension->ClockRate, ! 2620: (LONG)14400, ! 2621: &junk ! 2622: ))) { ! 2623: ! 2624: extension->SupportedBauds |= SERIAL_BAUD_14400; ! 2625: ! 2626: } ! 2627: ! 2628: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2629: extension->ClockRate, ! 2630: (LONG)19200, ! 2631: &junk ! 2632: ))) { ! 2633: ! 2634: extension->SupportedBauds |= SERIAL_BAUD_19200; ! 2635: ! 2636: } ! 2637: ! 2638: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2639: extension->ClockRate, ! 2640: (LONG)38400, ! 2641: &junk ! 2642: ))) { ! 2643: ! 2644: extension->SupportedBauds |= SERIAL_BAUD_38400; ! 2645: ! 2646: } ! 2647: ! 2648: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2649: extension->ClockRate, ! 2650: (LONG)56000, ! 2651: &junk ! 2652: ))) { ! 2653: ! 2654: extension->SupportedBauds |= SERIAL_BAUD_56K; ! 2655: ! 2656: } ! 2657: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2658: extension->ClockRate, ! 2659: (LONG)57600, ! 2660: &junk ! 2661: ))) { ! 2662: ! 2663: extension->SupportedBauds |= SERIAL_BAUD_57600; ! 2664: ! 2665: } ! 2666: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2667: extension->ClockRate, ! 2668: (LONG)115200, ! 2669: &junk ! 2670: ))) { ! 2671: ! 2672: extension->SupportedBauds |= SERIAL_BAUD_115200; ! 2673: ! 2674: } ! 2675: ! 2676: if (!NT_ERROR(SerialGetDivisorFromBaud( ! 2677: extension->ClockRate, ! 2678: (LONG)128000, ! 2679: &junk ! 2680: ))) { ! 2681: ! 2682: extension->SupportedBauds |= SERIAL_BAUD_128K; ! 2683: ! 2684: } ! 2685: ! 2686: } ! 2687: ! 2688: ! 2689: // ! 2690: // Mark this device as not being opened by anyone. We keep a ! 2691: // variable around so that spurious interrupts are easily ! 2692: // dismissed by the ISR. ! 2693: // ! 2694: ! 2695: extension->DeviceIsOpened = FALSE; ! 2696: ! 2697: // ! 2698: // This call will set up the naming necessary for ! 2699: // external applications to get to the driver. It ! 2700: // will also set up the device map. ! 2701: // ! 2702: ! 2703: ! 2704: extension->ObjectDirectory = ConfigData->ObjectDirectory; ! 2705: extension->NtNameForPort = ConfigData->NtNameForPort; ! 2706: extension->SymbolicLinkName = ConfigData->SymbolicLinkName; ! 2707: SerialSetupExternalNaming(extension); ! 2708: ! 2709: // ! 2710: // Store values into the extension for interval timing. ! 2711: // ! 2712: ! 2713: // ! 2714: // If the interval timer is less than a second then come ! 2715: // in with a short "polling" loop. ! 2716: // ! 2717: // For large (> then 2 seconds) use a 1 second poller. ! 2718: // ! 2719: ! 2720: extension->ShortIntervalAmount.LowPart = 1; ! 2721: extension->ShortIntervalAmount.HighPart = 0; ! 2722: extension->ShortIntervalAmount = RtlLargeIntegerNegate( ! 2723: extension->ShortIntervalAmount ! 2724: ); ! 2725: extension->LongIntervalAmount.LowPart = 10000000; ! 2726: extension->LongIntervalAmount.HighPart = 0; ! 2727: extension->LongIntervalAmount = RtlLargeIntegerNegate( ! 2728: extension->LongIntervalAmount ! 2729: ); ! 2730: extension->CutOverAmount.LowPart = 200000000; ! 2731: extension->CutOverAmount.HighPart = 0; ! 2732: ! 2733: ! 2734: // ! 2735: // Pass pack the extension to the caller. ! 2736: // ! 2737: ! 2738: *DeviceExtension = extension; ! 2739: ! 2740: // ! 2741: // Common error path cleanup. If the status is ! 2742: // bad, get rid of the device extension, device object ! 2743: // and any memory associated with it. ! 2744: // ! 2745: ! 2746: ExtensionCleanup: ; ! 2747: ! 2748: ExFreePool(ConfigData); ! 2749: ! 2750: if (NT_ERROR(status)) { ! 2751: ! 2752: if (extension) { ! 2753: ! 2754: if (reportedResources) { ! 2755: ! 2756: SerialUnReportResourcesDevice(extension); ! 2757: ! 2758: } ! 2759: ! 2760: SerialCleanupDevice(extension); ! 2761: IoDeleteDevice(deviceObject); ! 2762: ! 2763: } ! 2764: ! 2765: } ! 2766: ! 2767: return status; ! 2768: ! 2769: } ! 2770: ! 2771: BOOLEAN ! 2772: SerialDoesPortExist( ! 2773: IN PSERIAL_DEVICE_EXTENSION Extension, ! 2774: IN PUNICODE_STRING InsertString, ! 2775: IN ULONG ForceFifo ! 2776: ) ! 2777: ! 2778: /*++ ! 2779: ! 2780: Routine Description: ! 2781: ! 2782: This routine examines several of what might be the serial device ! 2783: registers. It ensures that the bits that should be zero are zero. ! 2784: ! 2785: In addition, this routine will determine if the device supports ! 2786: fifo's. If it does it will enable the fifo's and turn on a boolean ! 2787: in the extension that indicates the fifo's presence. ! 2788: ! 2789: NOTE: If there is indeed a serial port at the address specified ! 2790: it will absolutely have interrupts inhibited upon return ! 2791: from this routine. ! 2792: ! 2793: NOTE: Since this routine should be called fairly early in ! 2794: the device driver initialization, the only element ! 2795: that needs to be filled in is the base register address. ! 2796: ! 2797: NOTE: These tests all assume that this code is the only ! 2798: code that is looking at these ports or this memory. ! 2799: ! 2800: This is a not to unreasonable assumption even on ! 2801: multiprocessor systems. ! 2802: ! 2803: Arguments: ! 2804: ! 2805: Extension - A pointer to a serial device extension. ! 2806: InsertString - String to place in an error log entry. ! 2807: ForceFifo - !0 forces the fifo to be left on if found. ! 2808: ! 2809: Return Value: ! 2810: ! 2811: Will return true if the port really exists, otherwise it ! 2812: will return false. ! 2813: ! 2814: --*/ ! 2815: ! 2816: { ! 2817: ! 2818: ! 2819: UCHAR regContents; ! 2820: BOOLEAN returnValue = TRUE; ! 2821: UCHAR oldIERContents; ! 2822: UCHAR oldLCRContents; ! 2823: USHORT value1; ! 2824: USHORT value2; ! 2825: KIRQL oldIrql; ! 2826: ! 2827: ! 2828: // ! 2829: // Save of the line control. ! 2830: // ! 2831: ! 2832: oldLCRContents = READ_LINE_CONTROL(Extension->Controller); ! 2833: ! 2834: // ! 2835: // Make sure that we are *aren't* accessing the divsior latch. ! 2836: // ! 2837: ! 2838: WRITE_LINE_CONTROL( ! 2839: Extension->Controller, ! 2840: (UCHAR)(oldLCRContents & ~SERIAL_LCR_DLAB) ! 2841: ); ! 2842: ! 2843: oldIERContents = READ_INTERRUPT_ENABLE(Extension->Controller); ! 2844: ! 2845: // ! 2846: // Go up to power level for a very short time to prevent ! 2847: // any interrupts from this device from coming in. ! 2848: // ! 2849: ! 2850: KeRaiseIrql( ! 2851: POWER_LEVEL, ! 2852: &oldIrql ! 2853: ); ! 2854: ! 2855: WRITE_INTERRUPT_ENABLE( ! 2856: Extension->Controller, ! 2857: 0x0f ! 2858: ); ! 2859: ! 2860: value1 = READ_INTERRUPT_ENABLE(Extension->Controller); ! 2861: value1 = value1 << 8; ! 2862: value1 |= READ_RECEIVE_BUFFER(Extension->Controller); ! 2863: ! 2864: READ_DIVISOR_LATCH( ! 2865: Extension->Controller, ! 2866: &value2 ! 2867: ); ! 2868: ! 2869: WRITE_LINE_CONTROL( ! 2870: Extension->Controller, ! 2871: oldLCRContents ! 2872: ); ! 2873: ! 2874: // ! 2875: // Put the ier back to where it was before. If we are on a ! 2876: // level sensitive port this should prevent the interrupts ! 2877: // from coming in. If we are on a latched, we don't care ! 2878: // cause the interrupts generated will just get dropped. ! 2879: // ! 2880: ! 2881: WRITE_INTERRUPT_ENABLE( ! 2882: Extension->Controller, ! 2883: oldIERContents ! 2884: ); ! 2885: ! 2886: KeLowerIrql(oldIrql); ! 2887: ! 2888: if (value1 == value2) { ! 2889: ! 2890: SerialLogError( ! 2891: Extension->DeviceObject->DriverObject, ! 2892: Extension->DeviceObject, ! 2893: Extension->OriginalController, ! 2894: SerialPhysicalZero, ! 2895: 0, ! 2896: 0, ! 2897: 0, ! 2898: 62, ! 2899: STATUS_SUCCESS, ! 2900: SERIAL_DLAB_INVALID, ! 2901: InsertString->Length+sizeof(WCHAR), ! 2902: InsertString->Buffer, ! 2903: 0, ! 2904: NULL ! 2905: ); ! 2906: returnValue = FALSE; ! 2907: goto AllDone; ! 2908: ! 2909: } ! 2910: ! 2911: AllDone: ; ! 2912: ! 2913: ! 2914: // ! 2915: // If we think that there is a serial device then we determine ! 2916: // if a fifo is present. ! 2917: // ! 2918: ! 2919: if (returnValue) { ! 2920: ! 2921: // ! 2922: // Well, we think it's a serial device. Absolutely ! 2923: // positively, prevent interrupts from occuring. ! 2924: // ! 2925: // We disable all the interrupt enable bits, and ! 2926: // push down all the lines in the modem control ! 2927: // We only needed to push down OUT2 which in ! 2928: // PC's must also be enabled to get an interrupt. ! 2929: // ! 2930: ! 2931: DISABLE_ALL_INTERRUPTS(Extension->Controller); ! 2932: ! 2933: if (Extension->Jensen) { ! 2934: ! 2935: WRITE_MODEM_CONTROL( ! 2936: Extension->Controller, ! 2937: (UCHAR)SERIAL_MCR_OUT2 ! 2938: ); ! 2939: ! 2940: } else { ! 2941: ! 2942: WRITE_MODEM_CONTROL( ! 2943: Extension->Controller, ! 2944: (UCHAR)0 ! 2945: ); ! 2946: ! 2947: } ! 2948: ! 2949: // ! 2950: // See if this is a 16550. We do this by writing to ! 2951: // what would be the fifo control register with a bit ! 2952: // pattern that tells the device to enable fifo's. ! 2953: // We then read the iterrupt Id register to see if the ! 2954: // bit pattern is present that identifies the 16550. ! 2955: // ! 2956: ! 2957: WRITE_FIFO_CONTROL( ! 2958: Extension->Controller, ! 2959: SERIAL_FCR_ENABLE ! 2960: ); ! 2961: ! 2962: regContents = READ_INTERRUPT_ID_REG(Extension->Controller); ! 2963: ! 2964: if (regContents & SERIAL_IIR_FIFOS_ENABLED) { ! 2965: ! 2966: // ! 2967: // Save off that the device supports fifos. ! 2968: // ! 2969: ! 2970: Extension->FifoPresent = TRUE; ! 2971: ! 2972: // ! 2973: // There are fifos on this card. Set the value of the ! 2974: // receive fifo to interrupt when 4 characters are present. ! 2975: // ! 2976: ! 2977: WRITE_FIFO_CONTROL( ! 2978: Extension->Controller, ! 2979: (UCHAR)(SERIAL_FCR_ENABLE | Extension->RxFifoTrigger | ! 2980: SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET) ! 2981: ); ! 2982: ! 2983: } ! 2984: ! 2985: if (!ForceFifo) { ! 2986: ! 2987: Extension->FifoPresent = FALSE; ! 2988: WRITE_FIFO_CONTROL( ! 2989: Extension->Controller, ! 2990: (UCHAR)0 ! 2991: ); ! 2992: ! 2993: } ! 2994: ! 2995: if (Extension->FifoPresent) { ! 2996: ! 2997: SerialLogError( ! 2998: Extension->DeviceObject->DriverObject, ! 2999: Extension->DeviceObject, ! 3000: Extension->OriginalController, ! 3001: SerialPhysicalZero, ! 3002: 0, ! 3003: 0, ! 3004: 0, ! 3005: 15, ! 3006: STATUS_SUCCESS, ! 3007: SERIAL_FIFO_PRESENT, ! 3008: InsertString->Length+sizeof(WCHAR), ! 3009: InsertString->Buffer, ! 3010: 0, ! 3011: NULL ! 3012: ); ! 3013: ! 3014: SerialDump( ! 3015: SERDIAG1, ! 3016: ("SERIAL: Fifo's detected at port address: %x\n", ! 3017: Extension->Controller) ! 3018: ); ! 3019: ! 3020: } ! 3021: ! 3022: // ! 3023: // In case we are dealing with a bitmasked multiportcard, ! 3024: // that has the mask register enabled, enable all ! 3025: // interrupts. ! 3026: // ! 3027: ! 3028: if (Extension->InterruptStatus) { ! 3029: ! 3030: WRITE_PORT_UCHAR( ! 3031: Extension->InterruptStatus, ! 3032: (UCHAR)0xff ! 3033: ); ! 3034: ! 3035: } ! 3036: ! 3037: } ! 3038: ! 3039: return returnValue; ! 3040: ! 3041: } ! 3042: ! 3043: BOOLEAN ! 3044: SerialReset( ! 3045: IN PVOID Context ! 3046: ) ! 3047: ! 3048: /*++ ! 3049: ! 3050: Routine Description: ! 3051: ! 3052: This places the hardware in a standard configuration. ! 3053: ! 3054: NOTE: This assumes that it is called at interrupt level. ! 3055: ! 3056: ! 3057: Arguments: ! 3058: ! 3059: Context - The device extension for serial device ! 3060: being managed. ! 3061: ! 3062: Return Value: ! 3063: ! 3064: Always FALSE. ! 3065: ! 3066: --*/ ! 3067: ! 3068: { ! 3069: ! 3070: PSERIAL_DEVICE_EXTENSION extension = Context; ! 3071: UCHAR regContents; ! 3072: UCHAR oldModemControl; ! 3073: ULONG i; ! 3074: ! 3075: // ! 3076: // Deal with the out2 bit. ! 3077: // This will also prevent any interrupts from occuring. ! 3078: // ! 3079: ! 3080: oldModemControl = READ_MODEM_CONTROL(extension->Controller); ! 3081: ! 3082: if (extension->Jensen) { ! 3083: ! 3084: WRITE_MODEM_CONTROL( ! 3085: extension->Controller, ! 3086: (UCHAR)(oldModemControl | SERIAL_MCR_OUT2) ! 3087: ); ! 3088: ! 3089: } else { ! 3090: ! 3091: ! 3092: WRITE_MODEM_CONTROL( ! 3093: extension->Controller, ! 3094: (UCHAR)(oldModemControl & ~SERIAL_MCR_OUT2) ! 3095: ); ! 3096: ! 3097: } ! 3098: ! 3099: // ! 3100: // Reset the fifo's if there are any. ! 3101: // ! 3102: ! 3103: if (extension->FifoPresent) { ! 3104: ! 3105: WRITE_FIFO_CONTROL( ! 3106: extension->Controller, ! 3107: SERIAL_FCR_ENABLE ! 3108: ); ! 3109: WRITE_FIFO_CONTROL( ! 3110: extension->Controller, ! 3111: (UCHAR)(SERIAL_FCR_ENABLE | extension->RxFifoTrigger | ! 3112: SERIAL_FCR_RCVR_RESET | SERIAL_FCR_TXMT_RESET) ! 3113: ); ! 3114: ! 3115: } ! 3116: ! 3117: // ! 3118: // Make sure that the line control set up correct. ! 3119: // ! 3120: // 1) Make sure that the Divisor latch select is set ! 3121: // up to select the transmit and receive register. ! 3122: // ! 3123: // 2) Make sure that we aren't in a break state. ! 3124: // ! 3125: ! 3126: regContents = READ_LINE_CONTROL(extension->Controller); ! 3127: regContents &= ~(SERIAL_LCR_DLAB | SERIAL_LCR_BREAK); ! 3128: ! 3129: WRITE_LINE_CONTROL( ! 3130: extension->Controller, ! 3131: regContents ! 3132: ); ! 3133: ! 3134: // ! 3135: // Read the receive buffer until the line status is ! 3136: // clear. (Actually give up after a 5 reads.) ! 3137: // ! 3138: ! 3139: for (i = 0; ! 3140: i < 5; ! 3141: i++ ! 3142: ) { ! 3143: ! 3144: READ_RECEIVE_BUFFER(extension->Controller); ! 3145: if (!(READ_LINE_STATUS(extension->Controller) & 1)) { ! 3146: ! 3147: break; ! 3148: ! 3149: } ! 3150: ! 3151: } ! 3152: ! 3153: // ! 3154: // Read the modem status until the low 4 bits are ! 3155: // clear. (Actually give up after a 5 reads.) ! 3156: // ! 3157: ! 3158: for (i = 0; ! 3159: i < 1000; ! 3160: i++ ! 3161: ) { ! 3162: ! 3163: if (!(READ_MODEM_STATUS(extension->Controller) & 0x0f)) { ! 3164: ! 3165: break; ! 3166: ! 3167: } ! 3168: ! 3169: } ! 3170: ! 3171: // ! 3172: // Now we set the line control, modem control, and the ! 3173: // baud to what they should be. ! 3174: // ! 3175: ! 3176: SerialSetLineControl(extension); ! 3177: ! 3178: SerialSetupNewHandFlow( ! 3179: extension, ! 3180: &extension->HandFlow ! 3181: ); ! 3182: ! 3183: SerialHandleModemUpdate( ! 3184: extension, ! 3185: FALSE ! 3186: ); ! 3187: ! 3188: { ! 3189: SHORT appropriateDivisor; ! 3190: SERIAL_IOCTL_SYNC s; ! 3191: ! 3192: SerialGetDivisorFromBaud( ! 3193: extension->ClockRate, ! 3194: extension->CurrentBaud, ! 3195: &appropriateDivisor ! 3196: ); ! 3197: s.Extension = extension; ! 3198: s.Data = (PVOID)appropriateDivisor; ! 3199: SerialSetBaud(&s); ! 3200: } ! 3201: ! 3202: // ! 3203: // Enable which interrupts we want to receive. ! 3204: // ! 3205: // NOTE NOTE: This does not actually let interrupts ! 3206: // occur. We must still raise the OUT2 bit in the ! 3207: // modem control register. We will do that on open. ! 3208: // ! 3209: ! 3210: ENABLE_ALL_INTERRUPTS(extension->Controller); ! 3211: ! 3212: // ! 3213: // Read the interrupt id register until the low bit is ! 3214: // set. (Actually give up after a 5 reads.) ! 3215: // ! 3216: ! 3217: for (i = 0; ! 3218: i < 5; ! 3219: i++ ! 3220: ) { ! 3221: ! 3222: if (READ_INTERRUPT_ID_REG(extension->Controller) & 0x01) { ! 3223: ! 3224: break; ! 3225: ! 3226: } ! 3227: ! 3228: } ! 3229: ! 3230: // ! 3231: // Now we know that nothing could be transmitting at this point ! 3232: // so we set the HoldingEmpty indicator. ! 3233: // ! 3234: ! 3235: extension->HoldingEmpty = TRUE; ! 3236: ! 3237: return FALSE; ! 3238: } ! 3239: ! 3240: NTSTATUS ! 3241: SerialGetDivisorFromBaud( ! 3242: IN ULONG ClockRate, ! 3243: IN LONG DesiredBaud, ! 3244: OUT PSHORT AppropriateDivisor ! 3245: ) ! 3246: ! 3247: /*++ ! 3248: ! 3249: Routine Description: ! 3250: ! 3251: This routine will determine a divisor based on an unvalidated ! 3252: baud rate. ! 3253: ! 3254: Arguments: ! 3255: ! 3256: ClockRate - The clock input to the controller. ! 3257: ! 3258: DesiredBaud - The baud rate for whose divisor we seek. ! 3259: ! 3260: AppropriateDivisor - Given that the DesiredBaud is valid, the ! 3261: LONG pointed to by this parameter will be set to the appropriate ! 3262: value. NOTE: The long is undefined if the DesiredBaud is not ! 3263: supported. ! 3264: ! 3265: Return Value: ! 3266: ! 3267: This function will return STATUS_SUCCESS if the baud is supported. ! 3268: If the value is not supported it will return a status such that ! 3269: NT_ERROR(Status) == FALSE. ! 3270: ! 3271: --*/ ! 3272: ! 3273: { ! 3274: ! 3275: NTSTATUS status = STATUS_SUCCESS; ! 3276: SHORT calculatedDivisor; ! 3277: ULONG denominator; ! 3278: ULONG remainder; ! 3279: ! 3280: // ! 3281: // Allow up to a 1 percent error ! 3282: // ! 3283: ! 3284: ULONG maxRemain18 = 18432; ! 3285: ULONG maxRemain30 = 30720; ! 3286: ULONG maxRemain42 = 42336; ! 3287: ULONG maxRemain80 = 80000; ! 3288: ULONG maxRemain; ! 3289: ! 3290: // ! 3291: // Reject any non-positive bauds. ! 3292: // ! 3293: ! 3294: denominator = DesiredBaud*(ULONG)16; ! 3295: ! 3296: if (DesiredBaud <= 0) { ! 3297: ! 3298: *AppropriateDivisor = -1; ! 3299: ! 3300: } else if ((LONG)denominator < DesiredBaud) { ! 3301: ! 3302: // ! 3303: // If the desired baud was so huge that it cause the denominator ! 3304: // calculation to wrap, don't support it. ! 3305: // ! 3306: ! 3307: *AppropriateDivisor = -1; ! 3308: ! 3309: } else { ! 3310: ! 3311: if (ClockRate == 1843200) { ! 3312: maxRemain = maxRemain18; ! 3313: } else if (ClockRate == 3072000) { ! 3314: maxRemain = maxRemain30; ! 3315: } else if (ClockRate == 4233600) { ! 3316: maxRemain = maxRemain42; ! 3317: } else { ! 3318: maxRemain = maxRemain80; ! 3319: } ! 3320: ! 3321: calculatedDivisor = (SHORT)(ClockRate / denominator); ! 3322: remainder = ClockRate % denominator; ! 3323: ! 3324: // ! 3325: // Round up. ! 3326: // ! 3327: ! 3328: if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) { ! 3329: ! 3330: calculatedDivisor++; ! 3331: } ! 3332: ! 3333: ! 3334: // ! 3335: // Only let the remainder calculations effect us if ! 3336: // the baud rate is > 9600. ! 3337: // ! 3338: ! 3339: if (DesiredBaud >= 9600) { ! 3340: ! 3341: // ! 3342: // If the remainder is less than the maximum remainder (wrt ! 3343: // the ClockRate) or the remainder + the maximum remainder is ! 3344: // greater than or equal to the ClockRate then assume that the ! 3345: // baud is ok. ! 3346: // ! 3347: ! 3348: if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) { ! 3349: calculatedDivisor = -1; ! 3350: } ! 3351: ! 3352: } ! 3353: ! 3354: // ! 3355: // Don't support a baud that causes the denominator to ! 3356: // be larger than the clock. ! 3357: // ! 3358: ! 3359: if (denominator > ClockRate) { ! 3360: ! 3361: calculatedDivisor = -1; ! 3362: ! 3363: } ! 3364: ! 3365: // ! 3366: // Ok, Now do some special casing so that things can actually continue ! 3367: // working on all platforms. ! 3368: // ! 3369: ! 3370: if (ClockRate == 1843200) { ! 3371: ! 3372: if (DesiredBaud == 56000) { ! 3373: calculatedDivisor = 2; ! 3374: } ! 3375: ! 3376: } else if (ClockRate == 3072000) { ! 3377: ! 3378: if (DesiredBaud == 14400) { ! 3379: calculatedDivisor = 13; ! 3380: } ! 3381: ! 3382: } else if (ClockRate == 4233600) { ! 3383: ! 3384: if (DesiredBaud == 9600) { ! 3385: calculatedDivisor = 28; ! 3386: } else if (DesiredBaud == 14400) { ! 3387: calculatedDivisor = 18; ! 3388: } else if (DesiredBaud == 19200) { ! 3389: calculatedDivisor = 14; ! 3390: } else if (DesiredBaud == 38400) { ! 3391: calculatedDivisor = 7; ! 3392: } else if (DesiredBaud == 56000) { ! 3393: calculatedDivisor = 5; ! 3394: } ! 3395: ! 3396: } else if (ClockRate == 8000000) { ! 3397: ! 3398: if (DesiredBaud == 14400) { ! 3399: calculatedDivisor = 35; ! 3400: } else if (DesiredBaud == 56000) { ! 3401: calculatedDivisor = 9; ! 3402: } ! 3403: ! 3404: } ! 3405: ! 3406: *AppropriateDivisor = calculatedDivisor; ! 3407: ! 3408: } ! 3409: ! 3410: ! 3411: if (*AppropriateDivisor == -1) { ! 3412: ! 3413: status = STATUS_INVALID_PARAMETER; ! 3414: ! 3415: } ! 3416: ! 3417: return status; ! 3418: ! 3419: } ! 3420: ! 3421: VOID ! 3422: SerialUnload( ! 3423: IN PDRIVER_OBJECT DriverObject ! 3424: ) ! 3425: ! 3426: /*++ ! 3427: ! 3428: Routine Description: ! 3429: ! 3430: This routine cleans up all of the memory associated with ! 3431: any of the devices belonging to the driver. It will ! 3432: loop through the device list. ! 3433: ! 3434: Arguments: ! 3435: ! 3436: DriverObject - Pointer to the driver object controling all of the ! 3437: devices. ! 3438: ! 3439: Return Value: ! 3440: ! 3441: None. ! 3442: ! 3443: --*/ ! 3444: ! 3445: { ! 3446: ! 3447: PDEVICE_OBJECT currentDevice = DriverObject->DeviceObject; ! 3448: ! 3449: SerialDump( ! 3450: SERDIAG3, ! 3451: ("SERIAL: In SerialUnload\n") ! 3452: ); ! 3453: ! 3454: while (currentDevice) { ! 3455: ! 3456: PSERIAL_DEVICE_EXTENSION extension = currentDevice->DeviceExtension; ! 3457: ! 3458: // ! 3459: // Look for a device that actually has an isr. ! 3460: // if we find one then that is a "root" controller. ! 3461: // ! 3462: ! 3463: if (extension->OurIsr) { ! 3464: ! 3465: SerialDump( ! 3466: SERDIAG5, ! 3467: ("SERIAL: About to do a propagate delete on\n" ! 3468: "------- extension: %x for port %wZ\n", ! 3469: extension,&extension->DeviceName) ! 3470: ); ! 3471: SerialPropagateDeleteSharers( ! 3472: extension, ! 3473: &IoGetConfigurationInformation()->SerialCount, ! 3474: NULL ! 3475: ); ! 3476: ! 3477: currentDevice = DriverObject->DeviceObject; ! 3478: ! 3479: } else { ! 3480: ! 3481: currentDevice = currentDevice->NextDevice; ! 3482: ! 3483: } ! 3484: ! 3485: } ! 3486: ! 3487: } ! 3488: ! 3489: VOID ! 3490: SerialCleanupDevice( ! 3491: IN PSERIAL_DEVICE_EXTENSION Extension ! 3492: ) ! 3493: ! 3494: /*++ ! 3495: ! 3496: Routine Description: ! 3497: ! 3498: This routine will deallocate all of the memory used for ! 3499: a particular device. It will also disconnect any resources ! 3500: if need be. ! 3501: ! 3502: Arguments: ! 3503: ! 3504: Extension - Pointer to the device extension which is getting ! 3505: rid of all it's resources. ! 3506: ! 3507: Return Value: ! 3508: ! 3509: None. ! 3510: ! 3511: --*/ ! 3512: ! 3513: { ! 3514: ! 3515: SerialDump( ! 3516: SERDIAG3, ! 3517: ("SERIAL: in SerialCleanup for extension: %x\n",Extension) ! 3518: ); ! 3519: ! 3520: if (Extension) { ! 3521: ! 3522: // ! 3523: // Disconnect the interrupt object first so that some spurious ! 3524: // interrupt doesn't cause us to dereference some memory we've ! 3525: // already given up. ! 3526: // ! 3527: ! 3528: if (Extension->Interrupt) { ! 3529: ! 3530: SerialDump( ! 3531: SERDIAG5, ! 3532: ("SERIAL: Extension has interrupt %x\n",Extension) ! 3533: ); ! 3534: IoDisconnectInterrupt(Extension->Interrupt); ! 3535: ! 3536: } ! 3537: ! 3538: KeCancelTimer(&Extension->ReadRequestTotalTimer); ! 3539: KeCancelTimer(&Extension->ReadRequestIntervalTimer); ! 3540: KeCancelTimer(&Extension->WriteRequestTotalTimer); ! 3541: KeCancelTimer(&Extension->ImmediateTotalTimer); ! 3542: KeCancelTimer(&Extension->XoffCountTimer); ! 3543: KeCancelTimer(&Extension->LowerRTSTimer); ! 3544: KeRemoveQueueDpc(&Extension->CompleteWriteDpc); ! 3545: KeRemoveQueueDpc(&Extension->CompleteReadDpc); ! 3546: KeRemoveQueueDpc(&Extension->TotalReadTimeoutDpc); ! 3547: KeRemoveQueueDpc(&Extension->IntervalReadTimeoutDpc); ! 3548: KeRemoveQueueDpc(&Extension->TotalWriteTimeoutDpc); ! 3549: KeRemoveQueueDpc(&Extension->CommErrorDpc); ! 3550: KeRemoveQueueDpc(&Extension->CompleteImmediateDpc); ! 3551: KeRemoveQueueDpc(&Extension->TotalImmediateTimeoutDpc); ! 3552: KeRemoveQueueDpc(&Extension->CommWaitDpc); ! 3553: KeRemoveQueueDpc(&Extension->XoffCountTimeoutDpc); ! 3554: KeRemoveQueueDpc(&Extension->XoffCountCompleteDpc); ! 3555: KeRemoveQueueDpc(&Extension->StartTimerLowerRTSDpc); ! 3556: KeRemoveQueueDpc(&Extension->PerhapsLowerRTSDpc); ! 3557: ! 3558: // ! 3559: // Get rid of all external naming as well as removing ! 3560: // the device map entry. ! 3561: // ! 3562: ! 3563: SerialCleanupExternalNaming(Extension); ! 3564: ! 3565: // ! 3566: // Delallocate the memory for the various names. ! 3567: // NOTE: If we have an extension - Then we must ! 3568: // have a device name stored away. Which is *not* ! 3569: // true for the other names. ! 3570: // ! 3571: ! 3572: ExFreePool(Extension->DeviceName.Buffer); ! 3573: ! 3574: if (Extension->ObjectDirectory.Buffer) { ! 3575: ! 3576: ExFreePool(Extension->ObjectDirectory.Buffer); ! 3577: ! 3578: } ! 3579: ! 3580: if (Extension->NtNameForPort.Buffer) { ! 3581: ! 3582: ExFreePool(Extension->NtNameForPort.Buffer); ! 3583: ! 3584: } ! 3585: ! 3586: if (Extension->SymbolicLinkName.Buffer) { ! 3587: ! 3588: ExFreePool(Extension->SymbolicLinkName.Buffer); ! 3589: ! 3590: } ! 3591: ! 3592: // ! 3593: // If necessary, unmap the device registers. ! 3594: // ! 3595: ! 3596: if (Extension->UnMapRegisters) { ! 3597: ! 3598: MmUnmapIoSpace( ! 3599: Extension->Controller, ! 3600: Extension->SpanOfController ! 3601: ); ! 3602: ! 3603: } ! 3604: ! 3605: if (Extension->UnMapStatus) { ! 3606: ! 3607: MmUnmapIoSpace( ! 3608: Extension->InterruptStatus, ! 3609: Extension->SpanOfInterruptStatus ! 3610: ); ! 3611: ! 3612: } ! 3613: ! 3614: } ! 3615: ! 3616: } ! 3617: ! 3618: NTSTATUS ! 3619: SerialItemCallBack( ! 3620: IN PVOID Context, ! 3621: IN PUNICODE_STRING PathName, ! 3622: IN INTERFACE_TYPE BusType, ! 3623: IN ULONG BusNumber, ! 3624: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 3625: IN CONFIGURATION_TYPE ControllerType, ! 3626: IN ULONG ControllerNumber, ! 3627: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 3628: IN CONFIGURATION_TYPE PeripheralType, ! 3629: IN ULONG PeripheralNumber, ! 3630: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 3631: ) ! 3632: ! 3633: /*++ ! 3634: ! 3635: Routine Description: ! 3636: ! 3637: This routine is called to check if a particular item ! 3638: is present in the registry. ! 3639: ! 3640: Arguments: ! 3641: ! 3642: Context - Pointer to a boolean. ! 3643: ! 3644: PathName - unicode registry path. Not Used. ! 3645: ! 3646: BusType - Internal, Isa, ... ! 3647: ! 3648: BusNumber - Which bus if we are on a multibus system. ! 3649: ! 3650: BusInformation - Configuration information about the bus. Not Used. ! 3651: ! 3652: ControllerType - Controller type. ! 3653: ! 3654: ControllerNumber - Which controller if there is more than one ! 3655: controller in the system. ! 3656: ! 3657: ControllerInformation - Array of pointers to the three pieces of ! 3658: registry information. ! 3659: ! 3660: PeripheralType - Should be a peripheral. ! 3661: ! 3662: PeripheralNumber - Which peripheral - not used.. ! 3663: ! 3664: PeripheralInformation - Configuration information. Not Used. ! 3665: ! 3666: Return Value: ! 3667: ! 3668: STATUS_SUCCESS ! 3669: ! 3670: --*/ ! 3671: ! 3672: { ! 3673: ! 3674: *((BOOLEAN *)Context) = TRUE; ! 3675: return STATUS_SUCCESS; ! 3676: } ! 3677: ! 3678: // ! 3679: // This structure is only used to communicate between the ! 3680: // code that queries what the firmware found and the code ! 3681: // that is calling the quering of the firmware data. ! 3682: // ! 3683: typedef struct SERIAL_FIRMWARE_DATA { ! 3684: PDRIVER_OBJECT DriverObject; ! 3685: ULONG ControllersFound; ! 3686: ULONG ForceFifoEnableDefault; ! 3687: ULONG RxFIFODefault; ! 3688: UNICODE_STRING Directory; ! 3689: UNICODE_STRING NtNameSuffix; ! 3690: UNICODE_STRING DirectorySymbolicName; ! 3691: LIST_ENTRY ConfigList; ! 3692: } SERIAL_FIRMWARE_DATA,*PSERIAL_FIRMWARE_DATA; ! 3693: ! 3694: ! 3695: NTSTATUS ! 3696: SerialConfigCallBack( ! 3697: IN PVOID Context, ! 3698: IN PUNICODE_STRING PathName, ! 3699: IN INTERFACE_TYPE BusType, ! 3700: IN ULONG BusNumber, ! 3701: IN PKEY_VALUE_FULL_INFORMATION *BusInformation, ! 3702: IN CONFIGURATION_TYPE ControllerType, ! 3703: IN ULONG ControllerNumber, ! 3704: IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation, ! 3705: IN CONFIGURATION_TYPE PeripheralType, ! 3706: IN ULONG PeripheralNumber, ! 3707: IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation ! 3708: ) ! 3709: ! 3710: /*++ ! 3711: ! 3712: Routine Description: ! 3713: ! 3714: This routine is used to acquire all of the configuration ! 3715: information for each serial controller found by the firmware ! 3716: ! 3717: Arguments: ! 3718: ! 3719: Context - Pointer to the list head of the list of configuration ! 3720: records that we are building up. ! 3721: ! 3722: PathName - unicode registry path. Not Used. ! 3723: ! 3724: BusType - Internal, Isa, ... ! 3725: ! 3726: BusNumber - Which bus if we are on a multibus system. ! 3727: ! 3728: BusInformation - Configuration information about the bus. Not Used. ! 3729: ! 3730: ControllerType - Should always be SerialController. ! 3731: ! 3732: ControllerNumber - Which controller if there is more than one ! 3733: controller in the system. ! 3734: ! 3735: ControllerInformation - Array of pointers to the three pieces of ! 3736: registry information. ! 3737: ! 3738: PeripheralType - Undefined for this call. ! 3739: ! 3740: PeripheralNumber - Undefined for this call. ! 3741: ! 3742: PeripheralInformation - Undefined for this call. ! 3743: ! 3744: Return Value: ! 3745: ! 3746: STATUS_SUCCESS if everything went ok, or STATUS_INSUFFICIENT_RESOURCES ! 3747: if it couldn't map the base csr or acquire the device object, or ! 3748: all of the resource information couldn't be acquired. ! 3749: ! 3750: --*/ ! 3751: ! 3752: { ! 3753: ! 3754: // ! 3755: // So we don't have to typecast the context. ! 3756: // ! 3757: PSERIAL_FIRMWARE_DATA config = Context; ! 3758: ! 3759: // ! 3760: // Pointer to the configuration stuff for this controller. ! 3761: // ! 3762: PCONFIG_DATA controller; ! 3763: ! 3764: // ! 3765: // We use the following two variables to determine if ! 3766: // we have a pointer peripheral. ! 3767: // ! 3768: CONFIGURATION_TYPE pointer = PointerPeripheral; ! 3769: BOOLEAN foundPointer = FALSE; ! 3770: ! 3771: // ! 3772: // Two booleans to help us determine that we got enough configuration ! 3773: // data. ! 3774: // ! 3775: BOOLEAN foundPort = FALSE; ! 3776: BOOLEAN foundInterrupt = FALSE; ! 3777: ! 3778: // ! 3779: // Simple iteration variable. ! 3780: // ! 3781: ULONG i; ! 3782: ! 3783: PCM_FULL_RESOURCE_DESCRIPTOR controllerData; ! 3784: ! 3785: ASSERT(ControllerType == SerialController); ! 3786: ! 3787: config->ControllersFound++; ! 3788: ! 3789: // ! 3790: // Bail out if some fool wrote a hal and passed me data with no length. ! 3791: // ! 3792: ! 3793: if (!ControllerInformation[IoQueryDeviceConfigurationData]->DataLength) { ! 3794: ! 3795: return STATUS_SUCCESS; ! 3796: ! 3797: } ! 3798: ! 3799: controllerData = ! 3800: (PCM_FULL_RESOURCE_DESCRIPTOR) ! 3801: (((PUCHAR)ControllerInformation[IoQueryDeviceConfigurationData]) + ! 3802: ControllerInformation[IoQueryDeviceConfigurationData]->DataOffset); ! 3803: ! 3804: // ! 3805: // First things first. Call up IoQueryDeviceDescription ! 3806: // again to see if there is a pointer peripheral. If there ! 3807: // is then we simply ignore this controller. ! 3808: // ! 3809: ! 3810: IoQueryDeviceDescription( ! 3811: &BusType, ! 3812: &BusNumber, ! 3813: &ControllerType, ! 3814: &ControllerNumber, ! 3815: &pointer, ! 3816: NULL, ! 3817: SerialItemCallBack, ! 3818: &foundPointer ! 3819: ); ! 3820: ! 3821: if (foundPointer) { ! 3822: ! 3823: return STATUS_SUCCESS; ! 3824: ! 3825: } ! 3826: ! 3827: // ! 3828: // Allocate the memory for the controller config data out of paged pool ! 3829: // since we will only be accessing it at initialization time. ! 3830: // ! 3831: ! 3832: controller = ExAllocatePool( ! 3833: PagedPool, ! 3834: sizeof(CONFIG_DATA) ! 3835: ); ! 3836: ! 3837: if (!controller) { ! 3838: ! 3839: SerialLogError( ! 3840: config->DriverObject, ! 3841: NULL, ! 3842: SerialPhysicalZero, ! 3843: SerialPhysicalZero, ! 3844: 0, ! 3845: 0, ! 3846: 0, ! 3847: 16, ! 3848: STATUS_SUCCESS, ! 3849: SERIAL_INSUFFICIENT_RESOURCES, ! 3850: 0, ! 3851: NULL, ! 3852: 0, ! 3853: NULL ! 3854: ); ! 3855: SerialDump( ! 3856: SERERRORS, ! 3857: ("SERIAL: Couldn't allocate memory for the configuration data\n" ! 3858: "------ for firmware data\n") ! 3859: ); ! 3860: return STATUS_INSUFFICIENT_RESOURCES; ! 3861: ! 3862: } ! 3863: ! 3864: RtlZeroMemory( ! 3865: controller, ! 3866: sizeof(CONFIG_DATA) ! 3867: ); ! 3868: InitializeListHead(&controller->ConfigList); ! 3869: InitializeListHead(&controller->SameInterrupt); ! 3870: InitializeListHead(&controller->SameInterruptStatus); ! 3871: ! 3872: controller->InterfaceType = BusType; ! 3873: controller->BusNumber = BusNumber; ! 3874: ! 3875: // ! 3876: // Stick in the default fifo enable an rx trigger for the firmware ! 3877: // found comm ports. ! 3878: // ! 3879: ! 3880: controller->ForceFifoEnable = config->ForceFifoEnableDefault; ! 3881: controller->RxFIFO = config->RxFIFODefault; ! 3882: ! 3883: // ! 3884: // We need to get the following information out of the partial ! 3885: // resource descriptors. ! 3886: // ! 3887: // The irql and vector. ! 3888: // ! 3889: // The base address and span covered by the serial controllers ! 3890: // registers. ! 3891: // ! 3892: // It is not defined how these appear in the partial resource ! 3893: // lists, so we will just loop over all of them. If we find ! 3894: // something we don't recognize, we drop that information on ! 3895: // the floor. When we have finished going through all the ! 3896: // partial information, we validate that we got the above ! 3897: // two. ! 3898: // ! 3899: // The other additional piece of data that we seek is the ! 3900: // baud rate input clock speed. Unless it is specified ! 3901: // in the device specific portion of the resource list we ! 3902: // will default it to 1.8432Mhz. ! 3903: // ! 3904: ! 3905: controller->ClockRate = 1843200; ! 3906: for ( ! 3907: i = 0; ! 3908: i < controllerData->PartialResourceList.Count; ! 3909: i++ ! 3910: ) { ! 3911: ! 3912: PCM_PARTIAL_RESOURCE_DESCRIPTOR partial = ! 3913: &controllerData->PartialResourceList.PartialDescriptors[i]; ! 3914: ! 3915: switch (partial->Type) { ! 3916: ! 3917: case CmResourceTypePort: { ! 3918: ! 3919: foundPort = TRUE; ! 3920: ! 3921: // ! 3922: // No matter what the registry says, we ! 3923: // know how long the register set is. ! 3924: // ! 3925: ! 3926: controller->SpanOfController = SERIAL_REGISTER_SPAN; ! 3927: controller->Controller = partial->u.Port.Start; ! 3928: controller->AddressSpace = partial->Flags; ! 3929: ! 3930: break; ! 3931: } ! 3932: case CmResourceTypeInterrupt: { ! 3933: ! 3934: foundInterrupt = TRUE; ! 3935: if (partial->Flags & CM_RESOURCE_INTERRUPT_LATCHED) { ! 3936: ! 3937: controller->InterruptMode = Latched; ! 3938: ! 3939: } else { ! 3940: ! 3941: controller->InterruptMode = LevelSensitive; ! 3942: ! 3943: } ! 3944: ! 3945: controller->OriginalIrql = partial->u.Interrupt.Level; ! 3946: controller->OriginalVector = partial->u.Interrupt.Vector; ! 3947: ! 3948: break; ! 3949: ! 3950: } ! 3951: case CmResourceTypeDeviceSpecific: { ! 3952: ! 3953: PCM_SERIAL_DEVICE_DATA sDeviceData; ! 3954: ! 3955: sDeviceData = (PCM_SERIAL_DEVICE_DATA)(partial + 1); ! 3956: ! 3957: controller->ClockRate = sDeviceData->BaudClock; ! 3958: ! 3959: break; ! 3960: ! 3961: } ! 3962: default: { ! 3963: ! 3964: break; ! 3965: ! 3966: } ! 3967: ! 3968: } ! 3969: ! 3970: } ! 3971: ! 3972: if (foundPort && foundInterrupt) { ! 3973: ! 3974: WCHAR ntNumberBuffer[100]; ! 3975: WCHAR symbolicNumberBuffer[100]; ! 3976: UNICODE_STRING ntNumberString; ! 3977: UNICODE_STRING symbolicNumberString; ! 3978: ! 3979: ntNumberString.Length = 0; ! 3980: ntNumberString.MaximumLength = 100; ! 3981: ntNumberString.Buffer = &ntNumberBuffer[0]; ! 3982: ! 3983: symbolicNumberString.Length = 0; ! 3984: symbolicNumberString.MaximumLength = 100; ! 3985: symbolicNumberString.Buffer = &symbolicNumberBuffer[0]; ! 3986: ! 3987: // ! 3988: // Everthing is great so far. We now need to form the ! 3989: // Nt Names and symbolic link names. ! 3990: // ! 3991: ! 3992: if (!NT_SUCCESS(RtlIntegerToUnicodeString( ! 3993: config->ControllersFound - 1, ! 3994: 10, ! 3995: &ntNumberString ! 3996: ))) { ! 3997: ! 3998: SerialLogError( ! 3999: config->DriverObject, ! 4000: NULL, ! 4001: controller->Controller, ! 4002: SerialPhysicalZero, ! 4003: 0, ! 4004: 0, ! 4005: 0, ! 4006: 17, ! 4007: STATUS_SUCCESS, ! 4008: SERIAL_INSUFFICIENT_RESOURCES, ! 4009: 0, ! 4010: NULL, ! 4011: 0, ! 4012: NULL ! 4013: ); ! 4014: SerialDump( ! 4015: SERERRORS, ! 4016: ("SERIAL: Couldn't convert NT controller number to\n" ! 4017: "------ to unicode for firmware data: %d\n", ! 4018: config->ControllersFound - 1) ! 4019: ); ! 4020: // ! 4021: // Oh well, ignore this controller. ! 4022: // ! 4023: ExFreePool(controller); ! 4024: ! 4025: } else { ! 4026: ! 4027: if (!NT_SUCCESS(RtlIntegerToUnicodeString( ! 4028: config->ControllersFound, ! 4029: 10, ! 4030: &symbolicNumberString ! 4031: ))) { ! 4032: ! 4033: SerialLogError( ! 4034: config->DriverObject, ! 4035: NULL, ! 4036: controller->Controller, ! 4037: SerialPhysicalZero, ! 4038: 0, ! 4039: 0, ! 4040: 0, ! 4041: 18, ! 4042: STATUS_SUCCESS, ! 4043: SERIAL_INSUFFICIENT_RESOURCES, ! 4044: 0, ! 4045: NULL, ! 4046: 0, ! 4047: NULL ! 4048: ); ! 4049: SerialDump( ! 4050: SERERRORS, ! 4051: ("SERIAL: Couldn't allocate convert symbolic controller number to\n" ! 4052: "------ to unicode for firmware data: %d\n", ! 4053: config->ControllersFound) ! 4054: ); ! 4055: ExFreePool(controller); ! 4056: ! 4057: } else { ! 4058: ! 4059: UNICODE_STRING Temp; ! 4060: ! 4061: // ! 4062: // Ok, we have the non-constant portions of the ! 4063: // names all figured out. Now allocate memory ! 4064: // for what will be used later. ! 4065: // ! 4066: ! 4067: // ! 4068: // Save off a copy of the object directory name. ! 4069: // ! 4070: ! 4071: // ! 4072: // Init the destination. ! 4073: // ! 4074: RtlInitUnicodeString( ! 4075: &controller->ObjectDirectory, ! 4076: NULL ! 4077: ); ! 4078: ! 4079: // ! 4080: // This will get its length. ! 4081: // ! 4082: RtlInitUnicodeString( ! 4083: &Temp, ! 4084: DEFAULT_DIRECTORY ! 4085: ); ! 4086: ! 4087: // ! 4088: // Now allocate that much. ! 4089: // ! 4090: ! 4091: controller->ObjectDirectory.Buffer = ! 4092: ExAllocatePool( ! 4093: PagedPool, ! 4094: Temp.Length+sizeof(WCHAR) ! 4095: ); ! 4096: ! 4097: if (!controller->ObjectDirectory.Buffer) { ! 4098: ! 4099: SerialLogError( ! 4100: config->DriverObject, ! 4101: NULL, ! 4102: controller->Controller, ! 4103: SerialPhysicalZero, ! 4104: 0, ! 4105: 0, ! 4106: 0, ! 4107: 19, ! 4108: STATUS_SUCCESS, ! 4109: SERIAL_INSUFFICIENT_RESOURCES, ! 4110: 0, ! 4111: NULL, ! 4112: 0, ! 4113: NULL ! 4114: ); ! 4115: SerialDump( ! 4116: SERERRORS, ! 4117: ("SERIAL: Couldn't allocate memory for object\n" ! 4118: "------ directory for NT firmware data: %d\n", ! 4119: config->ControllersFound - 1) ! 4120: ); ! 4121: ExFreePool(controller); ! 4122: return STATUS_SUCCESS; ! 4123: ! 4124: } else { ! 4125: ! 4126: controller->ObjectDirectory.MaximumLength = ! 4127: Temp.Length+sizeof(WCHAR); ! 4128: ! 4129: // ! 4130: // Zero fill it. ! 4131: // ! 4132: ! 4133: RtlZeroMemory( ! 4134: controller->ObjectDirectory.Buffer, ! 4135: controller->ObjectDirectory.MaximumLength ! 4136: ); ! 4137: ! 4138: RtlAppendUnicodeStringToString( ! 4139: &controller->ObjectDirectory, ! 4140: &Temp ! 4141: ); ! 4142: ! 4143: } ! 4144: ! 4145: // ! 4146: // Init the destination. ! 4147: // ! 4148: RtlInitUnicodeString( ! 4149: &controller->NtNameForPort, ! 4150: NULL ! 4151: ); ! 4152: ! 4153: // ! 4154: // This will get its length. ! 4155: // ! 4156: RtlInitUnicodeString( ! 4157: &Temp, ! 4158: DEFAULT_NT_SUFFIX ! 4159: ); ! 4160: ! 4161: // ! 4162: // Allocate enough for the suffix and the number. ! 4163: // ! 4164: ! 4165: controller->NtNameForPort.Buffer = ! 4166: ExAllocatePool( ! 4167: PagedPool, ! 4168: Temp.Length + ! 4169: ntNumberString.Length + sizeof(WCHAR) ! 4170: ); ! 4171: ! 4172: if (!controller->NtNameForPort.Buffer) { ! 4173: ! 4174: SerialLogError( ! 4175: config->DriverObject, ! 4176: NULL, ! 4177: controller->Controller, ! 4178: SerialPhysicalZero, ! 4179: 0, ! 4180: 0, ! 4181: 0, ! 4182: 20, ! 4183: STATUS_SUCCESS, ! 4184: SERIAL_INSUFFICIENT_RESOURCES, ! 4185: 0, ! 4186: NULL, ! 4187: 0, ! 4188: NULL ! 4189: ); ! 4190: SerialDump( ! 4191: SERERRORS, ! 4192: ("SERIAL: Couldn't allocate memory for NT\n" ! 4193: "------ name for NT firmware data: %d\n", ! 4194: config->ControllersFound - 1) ! 4195: ); ! 4196: ExFreePool(controller->ObjectDirectory.Buffer); ! 4197: ExFreePool(controller); ! 4198: return STATUS_SUCCESS; ! 4199: ! 4200: } else { ! 4201: ! 4202: controller->NtNameForPort.MaximumLength = ! 4203: Temp.Length+ntNumberString.Length+sizeof(WCHAR); ! 4204: ! 4205: RtlZeroMemory( ! 4206: controller->NtNameForPort.Buffer, ! 4207: controller->NtNameForPort.MaximumLength ! 4208: ); ! 4209: ! 4210: RtlAppendUnicodeStringToString( ! 4211: &controller->NtNameForPort, ! 4212: &Temp ! 4213: ); ! 4214: ! 4215: RtlAppendUnicodeStringToString( ! 4216: &controller->NtNameForPort, ! 4217: &ntNumberString ! 4218: ); ! 4219: ! 4220: } ! 4221: ! 4222: // ! 4223: // Now form that name that will be used as a ! 4224: // symbolic link to the actual device name ! 4225: // we just formed. ! 4226: // ! 4227: ! 4228: RtlInitUnicodeString( ! 4229: &controller->SymbolicLinkName, ! 4230: NULL ! 4231: ); ! 4232: ! 4233: // ! 4234: // This will get its length. ! 4235: // ! 4236: RtlInitUnicodeString( ! 4237: &Temp, ! 4238: DEFAULT_SERIAL_NAME ! 4239: ); ! 4240: ! 4241: // ! 4242: // Allocate enough for the suffix and the number. ! 4243: // ! 4244: ! 4245: controller->SymbolicLinkName.Buffer = ! 4246: ExAllocatePool( ! 4247: PagedPool, ! 4248: Temp.Length + ! 4249: symbolicNumberString.Length+sizeof(WCHAR) ! 4250: ); ! 4251: ! 4252: if (!controller->SymbolicLinkName.Buffer) { ! 4253: ! 4254: SerialLogError( ! 4255: config->DriverObject, ! 4256: NULL, ! 4257: controller->Controller, ! 4258: SerialPhysicalZero, ! 4259: 0, ! 4260: 0, ! 4261: 0, ! 4262: 21, ! 4263: STATUS_SUCCESS, ! 4264: SERIAL_INSUFFICIENT_RESOURCES, ! 4265: 0, ! 4266: NULL, ! 4267: 0, ! 4268: NULL ! 4269: ); ! 4270: SerialDump( ! 4271: SERERRORS, ! 4272: ("SERIAL: Couldn't allocate memory for symbolic\n" ! 4273: "------ name for NT firmware data: %d\n", ! 4274: config->ControllersFound - 1) ! 4275: ); ! 4276: ExFreePool(controller->ObjectDirectory.Buffer); ! 4277: ExFreePool(controller->NtNameForPort.Buffer); ! 4278: ExFreePool(controller); ! 4279: return STATUS_SUCCESS; ! 4280: ! 4281: } else { ! 4282: ! 4283: controller->SymbolicLinkName.MaximumLength = ! 4284: Temp.Length+symbolicNumberString.Length+sizeof(WCHAR); ! 4285: ! 4286: RtlZeroMemory( ! 4287: controller->SymbolicLinkName.Buffer, ! 4288: controller->SymbolicLinkName.MaximumLength ! 4289: ); ! 4290: ! 4291: RtlAppendUnicodeStringToString( ! 4292: &controller->SymbolicLinkName, ! 4293: &Temp ! 4294: ); ! 4295: ! 4296: RtlAppendUnicodeStringToString( ! 4297: &controller->SymbolicLinkName, ! 4298: &symbolicNumberString ! 4299: ); ! 4300: ! 4301: } ! 4302: ! 4303: InsertTailList( ! 4304: &config->ConfigList, ! 4305: &controller->ConfigList ! 4306: ); ! 4307: ! 4308: } ! 4309: ! 4310: } ! 4311: ! 4312: } else { ! 4313: ! 4314: SerialLogError( ! 4315: config->DriverObject, ! 4316: NULL, ! 4317: controller->Controller, ! 4318: SerialPhysicalZero, ! 4319: 0, ! 4320: 0, ! 4321: 0, ! 4322: 22, ! 4323: STATUS_SUCCESS, ! 4324: SERIAL_NOT_ENOUGH_CONFIG_INFO, ! 4325: 0, ! 4326: NULL, ! 4327: 0, ! 4328: NULL ! 4329: ); ! 4330: ExFreePool(controller); ! 4331: ! 4332: } ! 4333: ! 4334: return STATUS_SUCCESS; ! 4335: } ! 4336: ! 4337: VOID ! 4338: SerialGetConfigInfo( ! 4339: IN PDRIVER_OBJECT DriverObject, ! 4340: IN PUNICODE_STRING RegistryPath, ! 4341: ULONG ForceFifoEnableDefault, ! 4342: ULONG RxFIFODefault, ! 4343: OUT PLIST_ENTRY ConfigList ! 4344: ) ! 4345: ! 4346: /*++ ! 4347: ! 4348: Routine Description: ! 4349: ! 4350: This routine will "return" a list of configuration ! 4351: records for the serial ports to initialize. ! 4352: ! 4353: It will first query the firmware data. It will then ! 4354: look for "user" specified comm ports in the registry. ! 4355: It will place the user specified comm ports in the ! 4356: the passed in list. ! 4357: ! 4358: After it finds all of the user specified port, it will ! 4359: attempt to add the firmware comm ports into the passed ! 4360: in lists. The insert in the list code detects conflicts ! 4361: and rejects a new comm port. In this way we can prevent ! 4362: firmware found comm ports from overiding information ! 4363: specified by the "user". Note, this means if the user ! 4364: specified data is incorrect in its use of the interrupt ! 4365: (which should *always* be correct from the firmware) ! 4366: that port likely will not work. But, then, we "trust" ! 4367: the user. ! 4368: ! 4369: ! 4370: Arguments: ! 4371: ! 4372: DriverObject - Not used. ! 4373: ! 4374: RegistryPath - Path to this drivers service node in ! 4375: the current control set. ! 4376: ! 4377: ForceFifoEnableDefault - Gotten from the services node. ! 4378: ! 4379: RxFifoDefault - Gotten from the services node. ! 4380: ! 4381: ConfigList - Listhead (which will be intialized) for a list ! 4382: of configuration records for ports to control. ! 4383: ! 4384: Return Value: ! 4385: ! 4386: STATUS_SUCCESS if consistant configuration was found - otherwise. ! 4387: returns STATUS_SERIAL_NO_DEVICE_INITED. ! 4388: ! 4389: --*/ ! 4390: ! 4391: { ! 4392: ! 4393: SERIAL_FIRMWARE_DATA firmware; ! 4394: ! 4395: PRTL_QUERY_REGISTRY_TABLE parameters = NULL; ! 4396: ! 4397: INTERFACE_TYPE interfaceType; ! 4398: ULONG defaultInterfaceType; ! 4399: ! 4400: ! 4401: // ! 4402: // Default values for user data. ! 4403: // ! 4404: ULONG maxUlong = MAXULONG; ! 4405: ULONG zero = 0; ! 4406: ULONG clockRate = 1843200; ! 4407: ULONG defaultInterruptMode; ! 4408: ULONG defaultAddressSpace = CM_RESOURCE_PORT_IO; ! 4409: ! 4410: // ! 4411: // Where user data from the registry will be placed. ! 4412: // ! 4413: ! 4414: PHYSICAL_ADDRESS userPort; ! 4415: ULONG userVector; ! 4416: ULONG userLevel; ! 4417: PHYSICAL_ADDRESS userInterruptStatus; ! 4418: ULONG userPortIndex; ! 4419: ULONG userBusNumber; ! 4420: ULONG userInterfaceType; ! 4421: ULONG userClockRate; ! 4422: ULONG userIndexed; ! 4423: ULONG userAddressSpace; ! 4424: ULONG userInterruptMode; ! 4425: ULONG firmwareFound; ! 4426: ULONG disablePort; ! 4427: ULONG forceFifoEnable; ! 4428: ULONG rxFIFO; ! 4429: UNICODE_STRING userSymbolicLink; ! 4430: ! 4431: UNICODE_STRING parametersPath; ! 4432: OBJECT_ATTRIBUTES parametersAttributes; ! 4433: HANDLE parametersKey; ! 4434: PKEY_BASIC_INFORMATION userSubKey = NULL; ! 4435: ULONG i; ! 4436: ! 4437: ! 4438: RTL_QUERY_REGISTRY_TABLE jensenTable[2] = {0}; ! 4439: UNICODE_STRING jensenData; ! 4440: UNICODE_STRING jensenValue; ! 4441: BOOLEAN jensenDetected; ! 4442: PUCHAR jensenBuffer; ! 4443: ! 4444: ! 4445: if (!(jensenBuffer = ExAllocatePool( ! 4446: PagedPool, ! 4447: 512 ! 4448: ))) { ! 4449: ! 4450: // ! 4451: // We couldn't allocate 512 bytes of paged pool. If that's ! 4452: // so, then it's likely that the least of this machines problem's ! 4453: // is that it's a Jensen. ! 4454: // ! 4455: ! 4456: jensenDetected = FALSE; ! 4457: ! 4458: } else { ! 4459: ! 4460: // ! 4461: // Check to see if this is a Jensen alpha. If we do, then ! 4462: // well have to change the way we enable and disable interrupts ! 4463: // ! 4464: ! 4465: jensenData.Length = 0; ! 4466: jensenData.MaximumLength = 512; ! 4467: jensenData.Buffer = (PWCHAR)&jensenBuffer[0]; ! 4468: RtlInitUnicodeString( ! 4469: &jensenValue, ! 4470: L"Jensen" ! 4471: ); ! 4472: jensenTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | ! 4473: RTL_QUERY_REGISTRY_REQUIRED; ! 4474: jensenTable[0].Name = L"Identifier"; ! 4475: jensenTable[0].EntryContext = &jensenData; ! 4476: ! 4477: if (!NT_SUCCESS(RtlQueryRegistryValues( ! 4478: RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, ! 4479: L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM", ! 4480: &jensenTable[0], ! 4481: NULL, ! 4482: NULL ! 4483: ))) { ! 4484: ! 4485: // ! 4486: // How odd, no identifer string! We'll it's probably not a jensen. ! 4487: // ! 4488: ! 4489: jensenDetected = FALSE; ! 4490: ! 4491: } else { ! 4492: ! 4493: // ! 4494: // Skip past the DEC-XX Portion of the name string. ! 4495: // Be carful and make sure we have at least that much data. ! 4496: // ! 4497: ! 4498: if (jensenData.Length <= (sizeof(WCHAR)*6)) { ! 4499: ! 4500: jensenDetected = FALSE; ! 4501: ! 4502: } else { ! 4503: ! 4504: jensenData.Length -= (sizeof(WCHAR)*6); ! 4505: jensenData.MaximumLength -= (sizeof(WCHAR)*6); ! 4506: jensenData.Buffer = (PWCHAR)&jensenBuffer[sizeof(WCHAR)*6]; ! 4507: jensenDetected = RtlEqualUnicodeString( ! 4508: &jensenData, ! 4509: &jensenValue, ! 4510: FALSE ! 4511: ); ! 4512: ! 4513: } ! 4514: ! 4515: } ! 4516: ! 4517: ExFreePool(jensenBuffer); ! 4518: ! 4519: } ! 4520: ! 4521: if (jensenDetected) { ! 4522: ! 4523: SerialDump( ! 4524: SERDIAG1, ! 4525: ("SERIAL: Jensen Detected\n") ! 4526: ); ! 4527: ! 4528: } ! 4529: ! 4530: InitializeListHead(ConfigList); ! 4531: ! 4532: RtlZeroMemory( ! 4533: &firmware, ! 4534: sizeof(SERIAL_FIRMWARE_DATA) ! 4535: ); ! 4536: ! 4537: firmware.DriverObject = DriverObject; ! 4538: firmware.ForceFifoEnableDefault = ForceFifoEnableDefault; ! 4539: firmware.RxFIFODefault = RxFIFODefault; ! 4540: InitializeListHead(&firmware.ConfigList); ! 4541: RtlInitUnicodeString( ! 4542: &firmware.Directory, ! 4543: DEFAULT_DIRECTORY ! 4544: ); ! 4545: RtlInitUnicodeString( ! 4546: &firmware.NtNameSuffix, ! 4547: DEFAULT_NT_SUFFIX ! 4548: ); ! 4549: RtlInitUnicodeString( ! 4550: &firmware.DirectorySymbolicName, ! 4551: DEFAULT_SERIAL_NAME ! 4552: ); ! 4553: ! 4554: // ! 4555: // First we query the hardware registry for all of ! 4556: // the firmware defined serial ports. We loop over ! 4557: // all of the busses. ! 4558: // ! 4559: ! 4560: for ( ! 4561: interfaceType = 0; ! 4562: interfaceType < MaximumInterfaceType; ! 4563: interfaceType++ ! 4564: ) { ! 4565: ! 4566: CONFIGURATION_TYPE sc = SerialController; ! 4567: ! 4568: IoQueryDeviceDescription( ! 4569: &interfaceType, ! 4570: NULL, ! 4571: &sc, ! 4572: NULL, ! 4573: NULL, ! 4574: NULL, ! 4575: SerialConfigCallBack, ! 4576: &firmware ! 4577: ); ! 4578: ! 4579: } ! 4580: ! 4581: // ! 4582: // Query the registry one more time. This time we ! 4583: // look for the first bus on the system (that isn't ! 4584: // the internal bus - we assume that the firmware ! 4585: // code knows about those ports). We will use that ! 4586: // as the default bus if no bustype or bus number ! 4587: // is specified in the "user" configuration records. ! 4588: // ! 4589: ! 4590: defaultInterfaceType = (ULONG)Isa; ! 4591: defaultInterruptMode = CM_RESOURCE_INTERRUPT_LATCHED; ! 4592: ! 4593: for ( ! 4594: interfaceType = 0; ! 4595: interfaceType < MaximumInterfaceType; ! 4596: interfaceType++ ! 4597: ) { ! 4598: ! 4599: ULONG busZero = 0; ! 4600: BOOLEAN foundOne = FALSE; ! 4601: ! 4602: if (interfaceType != Internal) { ! 4603: ! 4604: IoQueryDeviceDescription( ! 4605: &interfaceType, ! 4606: &busZero, ! 4607: NULL, ! 4608: NULL, ! 4609: NULL, ! 4610: NULL, ! 4611: SerialItemCallBack, ! 4612: &foundOne ! 4613: ); ! 4614: ! 4615: if (foundOne) { ! 4616: ! 4617: defaultInterfaceType = (ULONG)interfaceType; ! 4618: if (defaultInterfaceType == MicroChannel) { ! 4619: ! 4620: defaultInterruptMode = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 4621: ! 4622: } ! 4623: ! 4624: break; ! 4625: ! 4626: } ! 4627: ! 4628: } ! 4629: ! 4630: } ! 4631: ! 4632: // ! 4633: // Gonna get the user data now. Allocate the ! 4634: // structures that we will be using throughout ! 4635: // the search for user data. We will deallocate ! 4636: // them before we leave this routine. ! 4637: // ! 4638: ! 4639: userSymbolicLink.Buffer = NULL; ! 4640: parametersPath.Buffer = NULL; ! 4641: ! 4642: // ! 4643: // Allocate the rtl query table. This should have an entry for each value ! 4644: // we retrieve from the registry as well as a terminating zero entry as ! 4645: // well the first "goto subkey" entry. ! 4646: // ! 4647: ! 4648: parameters = ExAllocatePool( ! 4649: PagedPool, ! 4650: sizeof(RTL_QUERY_REGISTRY_TABLE)*18 ! 4651: ); ! 4652: ! 4653: if (!parameters) { ! 4654: ! 4655: SerialLogError( ! 4656: DriverObject, ! 4657: NULL, ! 4658: SerialPhysicalZero, ! 4659: SerialPhysicalZero, ! 4660: 0, ! 4661: 0, ! 4662: 0, ! 4663: 23, ! 4664: STATUS_SUCCESS, ! 4665: SERIAL_INSUFFICIENT_RESOURCES, ! 4666: 0, ! 4667: NULL, ! 4668: 0, ! 4669: NULL ! 4670: ); ! 4671: SerialDump( ! 4672: SERERRORS, ! 4673: ("SERIAL: Couldn't allocate table for rtl query\n" ! 4674: "------ to parameters for %wZ", ! 4675: RegistryPath) ! 4676: ); ! 4677: ! 4678: goto DoFirmwareAdd; ! 4679: ! 4680: } ! 4681: ! 4682: RtlZeroMemory( ! 4683: parameters, ! 4684: sizeof(RTL_QUERY_REGISTRY_TABLE)*18 ! 4685: ); ! 4686: ! 4687: // ! 4688: // Allocate the place where the users symbolic link name ! 4689: // for the port will go. ! 4690: // ! 4691: ! 4692: // ! 4693: // We will initially allocate space for 257 wchars. ! 4694: // we will then set the maximum size to 256 ! 4695: // This way the rtl routine could return a 256 ! 4696: // WCHAR wide string with no null terminator. ! 4697: // We'll remember that the buffer is one WCHAR ! 4698: // longer then it says it is so that we can always ! 4699: // have a NULL terminator at the end. ! 4700: // ! 4701: ! 4702: RtlInitUnicodeString( ! 4703: &userSymbolicLink, ! 4704: NULL ! 4705: ); ! 4706: userSymbolicLink.MaximumLength = sizeof(WCHAR)*256; ! 4707: userSymbolicLink.Buffer = ExAllocatePool( ! 4708: PagedPool, ! 4709: sizeof(WCHAR)*257 ! 4710: ); ! 4711: ! 4712: if (!userSymbolicLink.Buffer) { ! 4713: ! 4714: SerialLogError( ! 4715: DriverObject, ! 4716: NULL, ! 4717: SerialPhysicalZero, ! 4718: SerialPhysicalZero, ! 4719: 0, ! 4720: 0, ! 4721: 0, ! 4722: 24, ! 4723: STATUS_SUCCESS, ! 4724: SERIAL_INSUFFICIENT_RESOURCES, ! 4725: 0, ! 4726: NULL, ! 4727: 0, ! 4728: NULL ! 4729: ); ! 4730: SerialDump( ! 4731: SERERRORS, ! 4732: ("SERIAL: Couldn't allocate buffer for the symbolic link\n" ! 4733: "------ for parameters items in %wZ", ! 4734: RegistryPath) ! 4735: ); ! 4736: ! 4737: goto DoFirmwareAdd; ! 4738: ! 4739: } ! 4740: ! 4741: // ! 4742: // Form a path to our drivers Parameters subkey. ! 4743: // ! 4744: ! 4745: RtlInitUnicodeString( ! 4746: ¶metersPath, ! 4747: NULL ! 4748: ); ! 4749: ! 4750: parametersPath.MaximumLength = RegistryPath->Length + ! 4751: sizeof(L"\\") + ! 4752: sizeof(L"Parameters"); ! 4753: ! 4754: parametersPath.Buffer = ExAllocatePool( ! 4755: PagedPool, ! 4756: parametersPath.MaximumLength ! 4757: ); ! 4758: ! 4759: if (!parametersPath.Buffer) { ! 4760: ! 4761: SerialLogError( ! 4762: DriverObject, ! 4763: NULL, ! 4764: SerialPhysicalZero, ! 4765: SerialPhysicalZero, ! 4766: 0, ! 4767: 0, ! 4768: 0, ! 4769: 25, ! 4770: STATUS_SUCCESS, ! 4771: SERIAL_INSUFFICIENT_RESOURCES, ! 4772: 0, ! 4773: NULL, ! 4774: 0, ! 4775: NULL ! 4776: ); ! 4777: SerialDump( ! 4778: SERERRORS, ! 4779: ("SERIAL: Couldn't allocate string for path\n" ! 4780: "------ to parameters for %wZ", ! 4781: RegistryPath) ! 4782: ); ! 4783: ! 4784: goto DoFirmwareAdd; ! 4785: ! 4786: } ! 4787: ! 4788: // ! 4789: // Form the parameters path. ! 4790: // ! 4791: ! 4792: RtlZeroMemory( ! 4793: parametersPath.Buffer, ! 4794: parametersPath.MaximumLength ! 4795: ); ! 4796: RtlAppendUnicodeStringToString( ! 4797: ¶metersPath, ! 4798: RegistryPath ! 4799: ); ! 4800: RtlAppendUnicodeToString( ! 4801: ¶metersPath, ! 4802: L"\\" ! 4803: ); ! 4804: RtlAppendUnicodeToString( ! 4805: ¶metersPath, ! 4806: L"Parameters" ! 4807: ); ! 4808: ! 4809: userSubKey = ExAllocatePool( ! 4810: PagedPool, ! 4811: sizeof(KEY_BASIC_INFORMATION)+(sizeof(WCHAR)*256) ! 4812: ); ! 4813: ! 4814: if (!userSubKey) { ! 4815: ! 4816: SerialLogError( ! 4817: DriverObject, ! 4818: NULL, ! 4819: SerialPhysicalZero, ! 4820: SerialPhysicalZero, ! 4821: 0, ! 4822: 0, ! 4823: 0, ! 4824: 26, ! 4825: STATUS_SUCCESS, ! 4826: SERIAL_INSUFFICIENT_RESOURCES, ! 4827: 0, ! 4828: NULL, ! 4829: 0, ! 4830: NULL ! 4831: ); ! 4832: SerialDump( ! 4833: SERERRORS, ! 4834: ("SERIAL: Couldn't allocate memory basic information\n" ! 4835: "------ structure to enumerate subkeys for %wZ", ! 4836: ¶metersPath) ! 4837: ); ! 4838: ! 4839: goto DoFirmwareAdd; ! 4840: ! 4841: } ! 4842: ! 4843: // ! 4844: // Open the key given by our registry path & Parameters. ! 4845: // ! 4846: ! 4847: InitializeObjectAttributes( ! 4848: ¶metersAttributes, ! 4849: ¶metersPath, ! 4850: OBJ_CASE_INSENSITIVE, ! 4851: NULL, ! 4852: NULL ! 4853: ); ! 4854: ! 4855: if (!NT_SUCCESS(ZwOpenKey( ! 4856: ¶metersKey, ! 4857: MAXIMUM_ALLOWED, ! 4858: ¶metersAttributes ! 4859: ))) { ! 4860: ! 4861: SerialLogError( ! 4862: DriverObject, ! 4863: NULL, ! 4864: SerialPhysicalZero, ! 4865: SerialPhysicalZero, ! 4866: 0, ! 4867: 0, ! 4868: 0, ! 4869: 27, ! 4870: STATUS_SUCCESS, ! 4871: SERIAL_NO_PARAMETERS_INFO, ! 4872: 0, ! 4873: NULL, ! 4874: 0, ! 4875: NULL ! 4876: ); ! 4877: SerialDump( ! 4878: SERERRORS, ! 4879: ("SERIAL: Couldn't open the drivers Parameters key %wZ\n", ! 4880: RegistryPath) ! 4881: ); ! 4882: goto DoFirmwareAdd; ! 4883: ! 4884: } ! 4885: ! 4886: // ! 4887: // Gather all of the "user specified" information from ! 4888: // the registry. ! 4889: // ! 4890: ! 4891: parameters[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; ! 4892: ! 4893: parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4894: parameters[1].Name = L"PortAddress"; ! 4895: parameters[1].EntryContext = &userPort.LowPart; ! 4896: parameters[1].DefaultType = REG_DWORD; ! 4897: parameters[1].DefaultData = &zero; ! 4898: parameters[1].DefaultLength = sizeof(ULONG); ! 4899: ! 4900: parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4901: parameters[2].Name = L"Interrupt"; ! 4902: parameters[2].EntryContext = &userVector; ! 4903: parameters[2].DefaultType = REG_DWORD; ! 4904: parameters[2].DefaultData = &zero; ! 4905: parameters[2].DefaultLength = sizeof(ULONG); ! 4906: ! 4907: parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4908: parameters[3].Name = firmware.Directory.Buffer; ! 4909: parameters[3].EntryContext = &userSymbolicLink; ! 4910: parameters[3].DefaultType = REG_SZ; ! 4911: parameters[3].DefaultData = L""; ! 4912: parameters[3].DefaultLength = 0; ! 4913: ! 4914: parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4915: parameters[4].Name = L"InterruptStatus"; ! 4916: parameters[4].EntryContext = &userInterruptStatus.LowPart; ! 4917: parameters[4].DefaultType = REG_DWORD; ! 4918: parameters[4].DefaultData = &zero; ! 4919: parameters[4].DefaultLength = sizeof(ULONG); ! 4920: ! 4921: parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4922: parameters[5].Name = L"PortIndex"; ! 4923: parameters[5].EntryContext = &userPortIndex; ! 4924: parameters[5].DefaultType = REG_DWORD; ! 4925: parameters[5].DefaultData = &zero; ! 4926: parameters[5].DefaultLength = sizeof(ULONG); ! 4927: ! 4928: parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4929: parameters[6].Name = L"BusNumber"; ! 4930: parameters[6].EntryContext = &userBusNumber; ! 4931: parameters[6].DefaultType = REG_DWORD; ! 4932: parameters[6].DefaultData = &zero; ! 4933: parameters[6].DefaultLength = sizeof(ULONG); ! 4934: ! 4935: parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4936: parameters[7].Name = L"BusType"; ! 4937: parameters[7].EntryContext = &userInterfaceType; ! 4938: parameters[7].DefaultType = REG_DWORD; ! 4939: parameters[7].DefaultData = &defaultInterfaceType; ! 4940: parameters[7].DefaultLength = sizeof(ULONG); ! 4941: ! 4942: parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4943: parameters[8].Name = L"ClockRate"; ! 4944: parameters[8].EntryContext = &userClockRate; ! 4945: parameters[8].DefaultType = REG_DWORD; ! 4946: parameters[8].DefaultData = &clockRate; ! 4947: parameters[8].DefaultLength = sizeof(ULONG); ! 4948: ! 4949: parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4950: parameters[9].Name = L"Indexed"; ! 4951: parameters[9].EntryContext = &userIndexed; ! 4952: parameters[9].DefaultType = REG_DWORD; ! 4953: parameters[9].DefaultData = &zero; ! 4954: parameters[9].DefaultLength = sizeof(ULONG); ! 4955: ! 4956: parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4957: parameters[10].Name = L"InterruptMode"; ! 4958: parameters[10].EntryContext = &userInterruptMode; ! 4959: parameters[10].DefaultType = REG_DWORD; ! 4960: parameters[10].DefaultData = &defaultInterruptMode; ! 4961: parameters[10].DefaultLength = sizeof(ULONG); ! 4962: ! 4963: parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4964: parameters[11].Name = L"AddressSpace"; ! 4965: parameters[11].EntryContext = &userAddressSpace; ! 4966: parameters[11].DefaultType = REG_DWORD; ! 4967: parameters[11].DefaultData = &defaultAddressSpace; ! 4968: parameters[11].DefaultLength = sizeof(ULONG); ! 4969: ! 4970: parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4971: parameters[12].Name = L"InterruptLevel"; ! 4972: parameters[12].EntryContext = &userLevel; ! 4973: parameters[12].DefaultType = REG_DWORD; ! 4974: parameters[12].DefaultData = &zero; ! 4975: parameters[12].DefaultLength = sizeof(ULONG); ! 4976: ! 4977: parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4978: parameters[13].Name = L"FirmwareFound"; ! 4979: parameters[13].EntryContext = &firmwareFound; ! 4980: parameters[13].DefaultType = REG_DWORD; ! 4981: parameters[13].DefaultData = &zero; ! 4982: parameters[13].DefaultLength = sizeof(ULONG); ! 4983: ! 4984: parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4985: parameters[14].Name = L"DisablePort"; ! 4986: parameters[14].EntryContext = &disablePort; ! 4987: parameters[14].DefaultType = REG_DWORD; ! 4988: parameters[14].DefaultData = &zero; ! 4989: parameters[14].DefaultLength = sizeof(ULONG); ! 4990: ! 4991: parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4992: parameters[15].Name = L"ForceFifoEnable"; ! 4993: parameters[15].EntryContext = &forceFifoEnable; ! 4994: parameters[15].DefaultType = REG_DWORD; ! 4995: parameters[15].DefaultData = &ForceFifoEnableDefault; ! 4996: parameters[15].DefaultLength = sizeof(ULONG); ! 4997: ! 4998: parameters[16].Flags = RTL_QUERY_REGISTRY_DIRECT; ! 4999: parameters[16].Name = L"RxFIFO"; ! 5000: parameters[16].EntryContext = &rxFIFO; ! 5001: parameters[16].DefaultType = REG_DWORD; ! 5002: parameters[16].DefaultData = &RxFIFODefault; ! 5003: parameters[16].DefaultLength = sizeof(ULONG); ! 5004: ! 5005: ! 5006: ! 5007: i = 0; ! 5008: while (TRUE) { ! 5009: ! 5010: NTSTATUS status; ! 5011: ULONG actuallyReturned; ! 5012: ! 5013: // ! 5014: // We lie about the length of the buffer, so that we can ! 5015: // MAKE SURE that the name it returns can be padded with ! 5016: // a NULL. ! 5017: // ! 5018: ! 5019: status = ZwEnumerateKey( ! 5020: parametersKey, ! 5021: i, ! 5022: KeyBasicInformation, ! 5023: userSubKey, ! 5024: sizeof(KEY_BASIC_INFORMATION)+(sizeof(WCHAR)*255), ! 5025: &actuallyReturned ! 5026: ); ! 5027: ! 5028: if (status == STATUS_NO_MORE_ENTRIES) { ! 5029: ! 5030: break; ! 5031: } ! 5032: ! 5033: if (status == STATUS_BUFFER_OVERFLOW) { ! 5034: ! 5035: SerialLogError( ! 5036: DriverObject, ! 5037: NULL, ! 5038: SerialPhysicalZero, ! 5039: SerialPhysicalZero, ! 5040: 0, ! 5041: 0, ! 5042: 0, ! 5043: 28, ! 5044: STATUS_SUCCESS, ! 5045: SERIAL_UNABLE_TO_ACCESS_CONFIG, ! 5046: 0, ! 5047: NULL, ! 5048: 0, ! 5049: NULL ! 5050: ); ! 5051: SerialDump( ! 5052: SERERRORS, ! 5053: ("SERIAL: Overflowed the enumerate buffer\n" ! 5054: "------- for subkey #%d of %wZ\n", ! 5055: i,parametersPath) ! 5056: ); ! 5057: i++; ! 5058: continue; ! 5059: ! 5060: } ! 5061: ! 5062: if (!NT_SUCCESS(status)) { ! 5063: ! 5064: SerialLogError( ! 5065: DriverObject, ! 5066: NULL, ! 5067: SerialPhysicalZero, ! 5068: SerialPhysicalZero, ! 5069: 0, ! 5070: 0, ! 5071: 0, ! 5072: 29, ! 5073: status, ! 5074: SERIAL_UNABLE_TO_ACCESS_CONFIG, ! 5075: 0, ! 5076: NULL, ! 5077: 0, ! 5078: NULL ! 5079: ); ! 5080: SerialDump( ! 5081: SERERRORS, ! 5082: ("SERIAL: Bad status returned: %x \n" ! 5083: "------- on enumeration for subkey # %d of %wZ\n", ! 5084: status,i,parametersPath) ! 5085: ); ! 5086: i++; ! 5087: continue; ! 5088: ! 5089: } ! 5090: ! 5091: // ! 5092: // Pad the name returned with a null. ! 5093: // ! 5094: ! 5095: RtlZeroMemory( ! 5096: ((PUCHAR)(&userSubKey->Name[0]))+userSubKey->NameLength, ! 5097: sizeof(WCHAR) ! 5098: ); ! 5099: ! 5100: parameters[0].Name = &userSubKey->Name[0]; ! 5101: ! 5102: // ! 5103: // Make sure that the physical addresses start ! 5104: // out clean. ! 5105: // ! 5106: RtlZeroMemory( ! 5107: &userPort, ! 5108: sizeof(userPort) ! 5109: ); ! 5110: RtlZeroMemory( ! 5111: &userInterruptStatus, ! 5112: sizeof(userInterruptStatus) ! 5113: ); ! 5114: ! 5115: status = RtlQueryRegistryValues( ! 5116: RTL_REGISTRY_ABSOLUTE, ! 5117: parametersPath.Buffer, ! 5118: parameters, ! 5119: NULL, ! 5120: NULL ! 5121: ); ! 5122: ! 5123: if (NT_SUCCESS(status)) { ! 5124: ! 5125: PCONFIG_DATA newConfig; ! 5126: ! 5127: // ! 5128: // Well! Some supposedly valid information was found! ! 5129: // ! 5130: // We'll see about that. ! 5131: // ! 5132: // Make sure that the interrupt is non zero (which we defaulted ! 5133: // it to). ! 5134: // ! 5135: // Make sure that the portaddress is non zero (which we defaulted ! 5136: // it to). ! 5137: // ! 5138: // Make sure that the DosDevices is not NULL (which we defaulted ! 5139: // it to). ! 5140: // ! 5141: // We need to make sure that if an interrupt status ! 5142: // was specified, that a port index was also specfied, ! 5143: // and if so that the port index is <= maximum ports ! 5144: // on a board. ! 5145: // ! 5146: // We should also validate that the bus type and number ! 5147: // are correct. ! 5148: // ! 5149: // We will also validate that the interrupt mode makes ! 5150: // sense for the bus. ! 5151: // ! 5152: ! 5153: // ! 5154: // Let's just jam the WCHAR null at the end of the ! 5155: // user symbolic link. Remember that we left room for ! 5156: // one when we allocated it's buffer. ! 5157: // ! 5158: ! 5159: RtlZeroMemory( ! 5160: ((PUCHAR)(&userSymbolicLink.Buffer[0]))+userSymbolicLink.Length, ! 5161: sizeof(WCHAR) ! 5162: ); ! 5163: ! 5164: if (!userPort.LowPart) { ! 5165: ! 5166: // ! 5167: // Ehhhh! Lose Game. ! 5168: // ! 5169: ! 5170: SerialLogError( ! 5171: DriverObject, ! 5172: NULL, ! 5173: userPort, ! 5174: SerialPhysicalZero, ! 5175: 0, ! 5176: 0, ! 5177: 0, ! 5178: 58, ! 5179: STATUS_SUCCESS, ! 5180: SERIAL_INVALID_USER_CONFIG, ! 5181: userSubKey->NameLength+sizeof(WCHAR), ! 5182: &userSubKey->Name[0], ! 5183: (wcslen(parameters[1].Name)*sizeof(WCHAR))+sizeof(WCHAR), ! 5184: parameters[1].Name ! 5185: ); ! 5186: SerialDump( ! 5187: SERERRORS, ! 5188: ("SERIAL: Bogus port address %ws\n", ! 5189: parameters[1].Name) ! 5190: ); ! 5191: i++; ! 5192: continue; ! 5193: ! 5194: } ! 5195: ! 5196: if (!userVector) { ! 5197: ! 5198: // ! 5199: // Ehhhh! Lose Game. ! 5200: // ! 5201: ! 5202: SerialLogError( ! 5203: DriverObject, ! 5204: NULL, ! 5205: userPort, ! 5206: SerialPhysicalZero, ! 5207: 0, ! 5208: 0, ! 5209: 0, ! 5210: 59, ! 5211: STATUS_SUCCESS, ! 5212: SERIAL_INVALID_USER_CONFIG, ! 5213: userSubKey->NameLength+sizeof(WCHAR), ! 5214: &userSubKey->Name[0], ! 5215: (wcslen(parameters[2].Name)*sizeof(WCHAR))+sizeof(WCHAR), ! 5216: parameters[2].Name ! 5217: ); ! 5218: SerialDump( ! 5219: SERERRORS, ! 5220: ("SERIAL: Bogus vector %ws\n", ! 5221: parameters[2].Name) ! 5222: ); ! 5223: i++; ! 5224: continue; ! 5225: ! 5226: } ! 5227: ! 5228: if (!userSymbolicLink.Length) { ! 5229: ! 5230: // ! 5231: // Ehhhh! Lose Game. ! 5232: // ! 5233: ! 5234: SerialLogError( ! 5235: DriverObject, ! 5236: NULL, ! 5237: userPort, ! 5238: SerialPhysicalZero, ! 5239: 0, ! 5240: 0, ! 5241: 0, ! 5242: 60, ! 5243: STATUS_SUCCESS, ! 5244: SERIAL_INVALID_USER_CONFIG, ! 5245: userSubKey->NameLength+sizeof(WCHAR), ! 5246: &userSubKey->Name[0], ! 5247: (wcslen(parameters[3].Name)*sizeof(WCHAR))+sizeof(WCHAR), ! 5248: parameters[3].Name ! 5249: ); ! 5250: SerialDump( ! 5251: SERERRORS, ! 5252: ("SERIAL: bogus value for %ws\n", ! 5253: parameters[3].Name) ! 5254: ); ! 5255: i++; ! 5256: continue; ! 5257: ! 5258: } ! 5259: ! 5260: if (userInterruptStatus.LowPart != 0) { ! 5261: ! 5262: if (userPortIndex == MAXULONG) { ! 5263: ! 5264: // ! 5265: // Ehhhh! Lose Game. ! 5266: // ! 5267: ! 5268: SerialLogError( ! 5269: DriverObject, ! 5270: NULL, ! 5271: userPort, ! 5272: SerialPhysicalZero, ! 5273: 0, ! 5274: 0, ! 5275: 0, ! 5276: 30, ! 5277: STATUS_SUCCESS, ! 5278: SERIAL_INVALID_PORT_INDEX, ! 5279: userSymbolicLink.Length+sizeof(WCHAR), ! 5280: userSymbolicLink.Buffer, ! 5281: 0, ! 5282: NULL ! 5283: ); ! 5284: SerialDump( ! 5285: SERERRORS, ! 5286: ("SERIAL: Bogus port index %ws\n", ! 5287: parameters[0].Name) ! 5288: ); ! 5289: i++; ! 5290: continue; ! 5291: ! 5292: } else if (!userPortIndex) { ! 5293: ! 5294: // ! 5295: // So sorry, you must have a non-zero port index. ! 5296: // ! 5297: ! 5298: SerialLogError( ! 5299: DriverObject, ! 5300: NULL, ! 5301: userPort, ! 5302: SerialPhysicalZero, ! 5303: 0, ! 5304: 0, ! 5305: 0, ! 5306: 31, ! 5307: STATUS_SUCCESS, ! 5308: SERIAL_INVALID_PORT_INDEX, ! 5309: userSymbolicLink.Length+sizeof(WCHAR), ! 5310: userSymbolicLink.Buffer, ! 5311: 0, ! 5312: NULL ! 5313: ); ! 5314: SerialDump( ! 5315: SERERRORS, ! 5316: ("SERIAL: Port index must be > 0 for any\n" ! 5317: "------- port on a multiport card: %ws\n", ! 5318: parameters[0].Name) ! 5319: ); ! 5320: i++; ! 5321: continue; ! 5322: ! 5323: } else { ! 5324: ! 5325: if (userIndexed) { ! 5326: ! 5327: if (userPortIndex > SERIAL_MAX_PORTS_INDEXED) { ! 5328: ! 5329: SerialLogError( ! 5330: DriverObject, ! 5331: NULL, ! 5332: userPort, ! 5333: SerialPhysicalZero, ! 5334: 0, ! 5335: 0, ! 5336: 0, ! 5337: 32, ! 5338: STATUS_SUCCESS, ! 5339: SERIAL_PORT_INDEX_TOO_HIGH, ! 5340: userSymbolicLink.Length+sizeof(WCHAR), ! 5341: userSymbolicLink.Buffer, ! 5342: 0, ! 5343: NULL ! 5344: ); ! 5345: SerialDump( ! 5346: SERERRORS, ! 5347: ("SERIAL: port index to large %ws\n", ! 5348: parameters[0].Name) ! 5349: ); ! 5350: i++; ! 5351: continue; ! 5352: ! 5353: } ! 5354: ! 5355: } else { ! 5356: ! 5357: if (userPortIndex > SERIAL_MAX_PORTS_NONINDEXED) { ! 5358: ! 5359: SerialLogError( ! 5360: DriverObject, ! 5361: NULL, ! 5362: userPort, ! 5363: SerialPhysicalZero, ! 5364: 0, ! 5365: 0, ! 5366: 0, ! 5367: 33, ! 5368: STATUS_SUCCESS, ! 5369: SERIAL_PORT_INDEX_TOO_HIGH, ! 5370: userSymbolicLink.Length+sizeof(WCHAR), ! 5371: userSymbolicLink.Buffer, ! 5372: 0, ! 5373: NULL ! 5374: ); ! 5375: SerialDump( ! 5376: SERERRORS, ! 5377: ("SERIAL: port index to large %ws\n", ! 5378: parameters[0].Name) ! 5379: ); ! 5380: i++; ! 5381: continue; ! 5382: ! 5383: } ! 5384: ! 5385: } ! 5386: ! 5387: } ! 5388: ! 5389: } ! 5390: ! 5391: // ! 5392: // We don't want to cause the hal to have a bad day, ! 5393: // so let's check the interface type and bus number. ! 5394: // ! 5395: // We only need to check the registry if they aren't ! 5396: // equal to the defaults. ! 5397: // ! 5398: ! 5399: if ((userBusNumber != 0) || ! 5400: (userInterfaceType != defaultInterfaceType)) { ! 5401: ! 5402: BOOLEAN foundIt; ! 5403: if (userInterfaceType >= MaximumInterfaceType) { ! 5404: ! 5405: // ! 5406: // Ehhhh! Lose Game. ! 5407: // ! 5408: ! 5409: SerialLogError( ! 5410: DriverObject, ! 5411: NULL, ! 5412: userPort, ! 5413: SerialPhysicalZero, ! 5414: 0, ! 5415: 0, ! 5416: 0, ! 5417: 34, ! 5418: STATUS_SUCCESS, ! 5419: SERIAL_UNKNOWN_BUS, ! 5420: userSymbolicLink.Length+sizeof(WCHAR), ! 5421: userSymbolicLink.Buffer, ! 5422: 0, ! 5423: NULL ! 5424: ); ! 5425: SerialDump( ! 5426: SERERRORS, ! 5427: ("SERIAL: Invalid Bus type %ws\n", ! 5428: parameters[0].Name) ! 5429: ); ! 5430: i++; ! 5431: continue; ! 5432: ! 5433: } ! 5434: ! 5435: IoQueryDeviceDescription( ! 5436: (INTERFACE_TYPE *)&userInterfaceType, ! 5437: &zero, ! 5438: NULL, ! 5439: NULL, ! 5440: NULL, ! 5441: NULL, ! 5442: SerialItemCallBack, ! 5443: &foundIt ! 5444: ); ! 5445: ! 5446: if (!foundIt) { ! 5447: ! 5448: SerialLogError( ! 5449: DriverObject, ! 5450: NULL, ! 5451: userPort, ! 5452: SerialPhysicalZero, ! 5453: 0, ! 5454: 0, ! 5455: 0, ! 5456: 35, ! 5457: STATUS_SUCCESS, ! 5458: SERIAL_BUS_NOT_PRESENT, ! 5459: userSymbolicLink.Length+sizeof(WCHAR), ! 5460: userSymbolicLink.Buffer, ! 5461: 0, ! 5462: NULL ! 5463: ); ! 5464: SerialDump( ! 5465: SERERRORS, ! 5466: ("SERIAL: There aren't that many of those\n" ! 5467: "------- busses on this system,%ws\n", ! 5468: parameters[0].Name) ! 5469: ); ! 5470: i++; ! 5471: continue; ! 5472: ! 5473: } ! 5474: ! 5475: } ! 5476: ! 5477: if ((userInterfaceType == MicroChannel) && ! 5478: (userInterruptMode == CM_RESOURCE_INTERRUPT_LATCHED)) { ! 5479: ! 5480: SerialLogError( ! 5481: DriverObject, ! 5482: NULL, ! 5483: userPort, ! 5484: SerialPhysicalZero, ! 5485: 0, ! 5486: 0, ! 5487: 0, ! 5488: 36, ! 5489: STATUS_SUCCESS, ! 5490: SERIAL_BUS_INTERRUPT_CONFLICT, ! 5491: userSymbolicLink.Length+sizeof(WCHAR), ! 5492: userSymbolicLink.Buffer, ! 5493: 0, ! 5494: NULL ! 5495: ); ! 5496: SerialDump( ! 5497: SERERRORS, ! 5498: ("SERIAL: Latched interrupts and MicroChannel\n" ! 5499: "------- busses don't mix,%ws\n", ! 5500: parameters[0].Name) ! 5501: ); ! 5502: i++; ! 5503: continue; ! 5504: ! 5505: } ! 5506: ! 5507: // ! 5508: // Well ok, I guess we can take the data. ! 5509: // There be other tests later on to make ! 5510: // sure it doesn't have any other kinds ! 5511: // of conflicts. ! 5512: // ! 5513: ! 5514: // ! 5515: // Allocate the config record. ! 5516: // ! 5517: ! 5518: newConfig = ExAllocatePool( ! 5519: PagedPool, ! 5520: sizeof(CONFIG_DATA) ! 5521: ); ! 5522: ! 5523: if (!newConfig) { ! 5524: ! 5525: SerialLogError( ! 5526: DriverObject, ! 5527: NULL, ! 5528: userPort, ! 5529: SerialPhysicalZero, ! 5530: 0, ! 5531: 0, ! 5532: 0, ! 5533: 37, ! 5534: STATUS_SUCCESS, ! 5535: SERIAL_INSUFFICIENT_RESOURCES, ! 5536: 0, ! 5537: NULL, ! 5538: 0, ! 5539: NULL ! 5540: ); ! 5541: SerialDump( ! 5542: SERERRORS, ! 5543: ("SERIAL: Couldn't allocate memory for the\n" ! 5544: "------ user configuration record\n" ! 5545: "------ for %ws\n", ! 5546: parameters[0].Name) ! 5547: ); ! 5548: ! 5549: i++; ! 5550: continue; ! 5551: ! 5552: } ! 5553: ! 5554: RtlZeroMemory( ! 5555: newConfig, ! 5556: sizeof(CONFIG_DATA) ! 5557: ); ! 5558: ! 5559: // ! 5560: // Save off a copy of the object directory name. ! 5561: // ! 5562: ! 5563: // ! 5564: // Init the destination. ! 5565: // ! 5566: RtlInitUnicodeString( ! 5567: &newConfig->ObjectDirectory, ! 5568: DEFAULT_DIRECTORY ! 5569: ); ! 5570: newConfig->ObjectDirectory.MaximumLength += sizeof(WCHAR); ! 5571: ! 5572: // ! 5573: // Now allocate that much. ! 5574: // ! 5575: ! 5576: newConfig->ObjectDirectory.Buffer = ! 5577: ExAllocatePool( ! 5578: PagedPool, ! 5579: newConfig->ObjectDirectory.MaximumLength ! 5580: ); ! 5581: ! 5582: if (!newConfig->ObjectDirectory.Buffer) { ! 5583: ! 5584: SerialLogError( ! 5585: DriverObject, ! 5586: NULL, ! 5587: userPort, ! 5588: SerialPhysicalZero, ! 5589: 0, ! 5590: 0, ! 5591: 0, ! 5592: 38, ! 5593: STATUS_SUCCESS, ! 5594: SERIAL_INSUFFICIENT_RESOURCES, ! 5595: 0, ! 5596: NULL, ! 5597: 0, ! 5598: NULL ! 5599: ); ! 5600: SerialDump( ! 5601: SERERRORS, ! 5602: ("SERIAL: Couldn't allocate memory for object\n" ! 5603: "------ directory for NT user data for: %ws\n", ! 5604: parameters[0].Name) ! 5605: ); ! 5606: ExFreePool(newConfig); ! 5607: i++; ! 5608: continue; ! 5609: ! 5610: } else { ! 5611: ! 5612: // ! 5613: // Zero fill it. ! 5614: // ! 5615: ! 5616: RtlZeroMemory( ! 5617: newConfig->ObjectDirectory.Buffer, ! 5618: newConfig->ObjectDirectory.MaximumLength ! 5619: ); ! 5620: ! 5621: newConfig->ObjectDirectory.Length = 0; ! 5622: RtlAppendUnicodeToString( ! 5623: &newConfig->ObjectDirectory, ! 5624: DEFAULT_DIRECTORY ! 5625: ); ! 5626: ! 5627: } ! 5628: ! 5629: // ! 5630: // Init the destination. ! 5631: // ! 5632: RtlInitUnicodeString( ! 5633: &newConfig->NtNameForPort, ! 5634: &userSubKey->Name[0] ! 5635: ); ! 5636: ! 5637: // ! 5638: // Allocate the space for the name. ! 5639: // ! 5640: ! 5641: newConfig->NtNameForPort.Length = 0; ! 5642: newConfig->NtNameForPort.MaximumLength += sizeof(WCHAR); ! 5643: newConfig->NtNameForPort.Buffer = ! 5644: ExAllocatePool( ! 5645: PagedPool, ! 5646: newConfig->NtNameForPort.MaximumLength ! 5647: ); ! 5648: ! 5649: if (!newConfig->NtNameForPort.Buffer) { ! 5650: ! 5651: SerialLogError( ! 5652: DriverObject, ! 5653: NULL, ! 5654: userPort, ! 5655: SerialPhysicalZero, ! 5656: 0, ! 5657: 0, ! 5658: 0, ! 5659: 39, ! 5660: STATUS_SUCCESS, ! 5661: SERIAL_INSUFFICIENT_RESOURCES, ! 5662: 0, ! 5663: NULL, ! 5664: 0, ! 5665: NULL ! 5666: ); ! 5667: SerialDump( ! 5668: SERERRORS, ! 5669: ("SERIAL: Couldn't allocate memory for NT\n" ! 5670: "------ name for NT user data name: %ws\n", ! 5671: parameters[0].Name) ! 5672: ); ! 5673: ExFreePool(newConfig->ObjectDirectory.Buffer); ! 5674: ExFreePool(newConfig); ! 5675: i++; ! 5676: continue; ! 5677: ! 5678: } else { ! 5679: ! 5680: RtlZeroMemory( ! 5681: newConfig->NtNameForPort.Buffer, ! 5682: newConfig->NtNameForPort.MaximumLength ! 5683: ); ! 5684: ! 5685: RtlAppendUnicodeToString( ! 5686: &newConfig->NtNameForPort, ! 5687: &userSubKey->Name[0] ! 5688: ); ! 5689: ! 5690: } ! 5691: ! 5692: newConfig->SymbolicLinkName = userSymbolicLink; ! 5693: newConfig->SymbolicLinkName.MaximumLength += sizeof(WCHAR); ! 5694: ! 5695: newConfig->SymbolicLinkName.Buffer = ! 5696: ExAllocatePool( ! 5697: PagedPool, ! 5698: newConfig->SymbolicLinkName.MaximumLength ! 5699: ); ! 5700: ! 5701: if (!newConfig->SymbolicLinkName.Buffer) { ! 5702: ! 5703: SerialLogError( ! 5704: DriverObject, ! 5705: NULL, ! 5706: userPort, ! 5707: SerialPhysicalZero, ! 5708: 0, ! 5709: 0, ! 5710: 0, ! 5711: 40, ! 5712: STATUS_SUCCESS, ! 5713: SERIAL_INSUFFICIENT_RESOURCES, ! 5714: 0, ! 5715: NULL, ! 5716: 0, ! 5717: NULL ! 5718: ); ! 5719: SerialDump( ! 5720: SERERRORS, ! 5721: ("SERIAL: Couldn't allocate memory for symbolic\n" ! 5722: "------ name from user data\n" ! 5723: "------ %ws\n", ! 5724: parameters[0].Name) ! 5725: ); ! 5726: ExFreePool(newConfig->ObjectDirectory.Buffer); ! 5727: ExFreePool(newConfig->NtNameForPort.Buffer); ! 5728: ExFreePool(newConfig); ! 5729: i++; ! 5730: continue; ! 5731: ! 5732: } else { ! 5733: ! 5734: RtlZeroMemory( ! 5735: newConfig->SymbolicLinkName.Buffer, ! 5736: newConfig->SymbolicLinkName.MaximumLength ! 5737: ); ! 5738: ! 5739: newConfig->SymbolicLinkName.Length = 0; ! 5740: RtlAppendUnicodeStringToString( ! 5741: &newConfig->SymbolicLinkName, ! 5742: &userSymbolicLink ! 5743: ); ! 5744: ! 5745: } ! 5746: ! 5747: InitializeListHead(&newConfig->ConfigList); ! 5748: InitializeListHead(&newConfig->SameInterrupt); ! 5749: InitializeListHead(&newConfig->SameInterruptStatus); ! 5750: newConfig->Controller = userPort; ! 5751: newConfig->InterruptStatus = userInterruptStatus; ! 5752: newConfig->SpanOfController = SERIAL_REGISTER_SPAN; ! 5753: newConfig->SpanOfInterruptStatus = SERIAL_STATUS_LENGTH; ! 5754: newConfig->PortIndex = userPortIndex; ! 5755: newConfig->ClockRate = userClockRate; ! 5756: newConfig->BusNumber = userBusNumber; ! 5757: newConfig->AddressSpace = userAddressSpace; ! 5758: newConfig->InterruptMode = userInterruptMode; ! 5759: newConfig->InterfaceType = userInterfaceType; ! 5760: newConfig->OriginalVector = userVector; ! 5761: newConfig->DisablePort = disablePort; ! 5762: newConfig->ForceFifoEnable = forceFifoEnable; ! 5763: newConfig->RxFIFO = rxFIFO; ! 5764: if (!userLevel) { ! 5765: newConfig->OriginalIrql = userVector; ! 5766: } else { ! 5767: newConfig->OriginalIrql = userLevel; ! 5768: } ! 5769: newConfig->Indexed = userIndexed; ! 5770: SerialDump( ! 5771: SERDIAG1, ! 5772: ("SERIAL: 'user registry info - userPort: %x\n", ! 5773: userPort.LowPart) ! 5774: ); ! 5775: SerialDump( ! 5776: SERDIAG1, ! 5777: ("SERIAL: 'user registry info - userInterruptStatus: %x\n", ! 5778: userInterruptStatus.LowPart) ! 5779: ); ! 5780: SerialDump( ! 5781: SERDIAG1, ! 5782: ("SERIAL: 'user registry info - userPortIndex: %d\n", ! 5783: userPortIndex) ! 5784: ); ! 5785: SerialDump( ! 5786: SERDIAG1, ! 5787: ("SERIAL: 'user registry info - userClockRate: %d\n", ! 5788: userClockRate) ! 5789: ); ! 5790: SerialDump( ! 5791: SERDIAG1, ! 5792: ("SERIAL: 'user registry info - userBusNumber: %d\n", ! 5793: userBusNumber) ! 5794: ); ! 5795: SerialDump( ! 5796: SERDIAG1, ! 5797: ("SERIAL: 'user registry info - userAddressSpace: %d\n", ! 5798: userAddressSpace) ! 5799: ); ! 5800: SerialDump( ! 5801: SERDIAG1, ! 5802: ("SERIAL: 'user registry info - userInterruptMode: %d\n", ! 5803: userInterruptMode) ! 5804: ); ! 5805: SerialDump( ! 5806: SERDIAG1, ! 5807: ("SERIAL: 'user registry info - userInterfaceType: %d\n", ! 5808: userInterfaceType) ! 5809: ); ! 5810: SerialDump( ! 5811: SERDIAG1, ! 5812: ("SERIAL: 'user registry info - userVector: %d\n", ! 5813: userVector) ! 5814: ); ! 5815: SerialDump( ! 5816: SERDIAG1, ! 5817: ("SERIAL: 'user registry info - userLevel: %d\n", ! 5818: userLevel) ! 5819: ); ! 5820: SerialDump( ! 5821: SERDIAG1, ! 5822: ("SERIAL: 'user registry info - userIndexed: %d\n", ! 5823: userIndexed) ! 5824: ); ! 5825: ! 5826: if (!SerialPutInConfigList( ! 5827: DriverObject, ! 5828: ConfigList, ! 5829: newConfig ! 5830: )) { ! 5831: ! 5832: // ! 5833: // Dispose of this configuration record. ! 5834: // ! 5835: ! 5836: SerialDump( ! 5837: SERERRORS, ! 5838: ("SERIAL: Conflict detected amoungst user data %ws\n", ! 5839: parameters[0].Name) ! 5840: ); ! 5841: ! 5842: ExFreePool(newConfig->ObjectDirectory.Buffer); ! 5843: ExFreePool(newConfig->NtNameForPort.Buffer); ! 5844: ExFreePool(newConfig->SymbolicLinkName.Buffer); ! 5845: ExFreePool(newConfig); ! 5846: ! 5847: } ! 5848: ! 5849: i++; ! 5850: ! 5851: } else { ! 5852: ! 5853: SerialLogError( ! 5854: DriverObject, ! 5855: NULL, ! 5856: SerialPhysicalZero, ! 5857: SerialPhysicalZero, ! 5858: 0, ! 5859: 0, ! 5860: 0, ! 5861: 61, ! 5862: status, ! 5863: SERIAL_INVALID_USER_CONFIG, ! 5864: userSubKey->NameLength+sizeof(WCHAR), ! 5865: &userSubKey->Name[0], ! 5866: 0, ! 5867: NULL ! 5868: ); ! 5869: SerialDump( ! 5870: SERERRORS, ! 5871: ("SERIAL: Bad status returned: %x \n" ! 5872: "------- for the value entries of\n" ! 5873: "------- %ws\n", ! 5874: status,parameters[0].Name) ! 5875: ); ! 5876: ! 5877: i++; ! 5878: ! 5879: } ! 5880: ! 5881: } ! 5882: ! 5883: ZwClose(parametersKey); ! 5884: ! 5885: DoFirmwareAdd:; ! 5886: ! 5887: // ! 5888: // All done with the user specified information. Now try ! 5889: // to add the firmware specified data to the configuration. ! 5890: // If a conflict is detected then we simply dispose of that ! 5891: // firmware collected data. ! 5892: // ! 5893: ! 5894: while (!IsListEmpty(&firmware.ConfigList)) { ! 5895: ! 5896: PLIST_ENTRY head; ! 5897: PCONFIG_DATA firmwareData; ! 5898: ! 5899: head = RemoveHeadList(&firmware.ConfigList); ! 5900: ! 5901: firmwareData = CONTAINING_RECORD( ! 5902: head, ! 5903: CONFIG_DATA, ! 5904: ConfigList ! 5905: ); ! 5906: ! 5907: ! 5908: firmwareData->Jensen = jensenDetected; ! 5909: ! 5910: if (!SerialPutInConfigList( ! 5911: DriverObject, ! 5912: ConfigList, ! 5913: firmwareData ! 5914: )) { ! 5915: ! 5916: // ! 5917: // Dispose of this configuration record. ! 5918: // ! 5919: ! 5920: SerialLogError( ! 5921: DriverObject, ! 5922: NULL, ! 5923: firmwareData->Controller, ! 5924: SerialPhysicalZero, ! 5925: 0, ! 5926: 0, ! 5927: 0, ! 5928: 42, ! 5929: STATUS_SUCCESS, ! 5930: SERIAL_USER_OVERRIDE, ! 5931: firmwareData->SymbolicLinkName.Length+sizeof(WCHAR), ! 5932: firmwareData->SymbolicLinkName.Buffer, ! 5933: 0, ! 5934: NULL ! 5935: ); ! 5936: SerialDump( ! 5937: SERERRORS, ! 5938: ("SERIAL: Conflict detected with user data for firmware port %wZ\n" ! 5939: "------ User data will overides firmware data\n", ! 5940: &firmwareData->NtNameForPort) ! 5941: ); ! 5942: ExFreePool(firmwareData->ObjectDirectory.Buffer); ! 5943: ExFreePool(firmwareData->NtNameForPort.Buffer); ! 5944: ExFreePool(firmwareData->SymbolicLinkName.Buffer); ! 5945: ExFreePool(firmwareData); ! 5946: ! 5947: } ! 5948: ! 5949: } ! 5950: ! 5951: if (userSubKey) { ! 5952: ! 5953: ExFreePool(userSubKey); ! 5954: ! 5955: } ! 5956: ! 5957: if (userSymbolicLink.Buffer) { ! 5958: ! 5959: ExFreePool(userSymbolicLink.Buffer); ! 5960: ! 5961: } ! 5962: ! 5963: if (parametersPath.Buffer) { ! 5964: ! 5965: ExFreePool(parametersPath.Buffer); ! 5966: ! 5967: } ! 5968: ! 5969: if (parameters) { ! 5970: ! 5971: ExFreePool(parameters); ! 5972: ! 5973: } ! 5974: } ! 5975: ! 5976: BOOLEAN ! 5977: SerialPutInConfigList( ! 5978: IN PDRIVER_OBJECT DriverObject, ! 5979: IN OUT PLIST_ENTRY ConfigList, ! 5980: IN PCONFIG_DATA New ! 5981: ) ! 5982: ! 5983: /*++ ! 5984: ! 5985: Routine Description: ! 5986: ! 5987: Given an interrupt value, port address, interrupt status address, ! 5988: and an already defined list of configuration records, this routine ! 5989: will perform a check to make sure that the new record doesn't ! 5990: conflict with old records. (Note that we also include a port ! 5991: index, but this has no bearing on validation.) ! 5992: ! 5993: If everything checks out it will create a new configuration ! 5994: record if the new record isn't part of multiport card or ! 5995: if it is part of a multiport card it will create a configuration ! 5996: record if the specifiers for that multiport card don't already ! 5997: exist. ! 5998: ! 5999: NOTE: It is assumed throughout this code that no address is ! 6000: specified as 0. ! 6001: ! 6002: We assume nothing is zero because that for interrupt ! 6003: status that means none was specified. ! 6004: ! 6005: Arguments: ! 6006: ! 6007: DriverObject - Used to log errors. ! 6008: ! 6009: ConfigList - Listhead for a list of configuration records for ! 6010: ports to control. ! 6011: ! 6012: New = Pointer to new configuration record to add. ! 6013: ! 6014: Return Value: ! 6015: ! 6016: This will return STATUS_SUCCESS this new port information ! 6017: does not conflict with old port information. Otherwise it ! 6018: will return STATUS_SERIAL_NO_DEVICE_INITED. ! 6019: ! 6020: --*/ ! 6021: ! 6022: { ! 6023: ! 6024: PHYSICAL_ADDRESS serialPhysicalMax; ! 6025: ! 6026: serialPhysicalMax.LowPart = (ULONG)~0; ! 6027: serialPhysicalMax.HighPart = ~0; ! 6028: ! 6029: SerialDump( ! 6030: SERDIAG1, ! 6031: ("SERIAL: Attempting to add %wZ\n" ! 6032: "------- to the config list\n" ! 6033: "------- PortAddress is %x\n" ! 6034: "------- Interrupt Status is %x\n" ! 6035: "------- BusNumber is %d\n" ! 6036: "------- BusType is %d\n" ! 6037: "------- AddressSpace is %d\n", ! 6038: &New->NtNameForPort, ! 6039: New->Controller.LowPart, ! 6040: New->InterruptStatus.LowPart, ! 6041: New->BusNumber, ! 6042: New->InterfaceType, ! 6043: New->AddressSpace ! 6044: ) ! 6045: ); ! 6046: ! 6047: // ! 6048: // We don't support any boards whose memory wraps around ! 6049: // the physical address space. ! 6050: // ! 6051: ! 6052: if (SerialMemCompare( ! 6053: New->Controller, ! 6054: New->SpanOfController, ! 6055: serialPhysicalMax, ! 6056: (ULONG)0 ! 6057: ) != AddressesAreDisjoint) { ! 6058: ! 6059: SerialLogError( ! 6060: DriverObject, ! 6061: NULL, ! 6062: New->Controller, ! 6063: SerialPhysicalZero, ! 6064: 0, ! 6065: 0, ! 6066: 0, ! 6067: 43, ! 6068: STATUS_SUCCESS, ! 6069: SERIAL_DEVICE_TOO_HIGH, ! 6070: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6071: New->SymbolicLinkName.Buffer, ! 6072: 0, ! 6073: NULL ! 6074: ); ! 6075: SerialDump( ! 6076: SERERRORS, ! 6077: ("SERIAL: Error in config record for %wZ\n" ! 6078: "------ registers rap around physical memory\n", ! 6079: &New->NtNameForPort) ! 6080: ); ! 6081: return FALSE; ! 6082: ! 6083: } ! 6084: ! 6085: if (SerialMemCompare( ! 6086: New->InterruptStatus, ! 6087: New->SpanOfInterruptStatus, ! 6088: serialPhysicalMax, ! 6089: (ULONG)0 ! 6090: ) != AddressesAreDisjoint) { ! 6091: ! 6092: SerialLogError( ! 6093: DriverObject, ! 6094: NULL, ! 6095: New->Controller, ! 6096: SerialPhysicalZero, ! 6097: 0, ! 6098: 0, ! 6099: 0, ! 6100: 44, ! 6101: STATUS_SUCCESS, ! 6102: SERIAL_STATUS_TOO_HIGH, ! 6103: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6104: New->SymbolicLinkName.Buffer, ! 6105: 0, ! 6106: NULL ! 6107: ); ! 6108: SerialDump( ! 6109: SERERRORS, ! 6110: ("SERIAL: Error in config record for %wZ\n" ! 6111: "------ status raps around physical memory\n", ! 6112: &New->NtNameForPort) ! 6113: ); ! 6114: return FALSE; ! 6115: ! 6116: } ! 6117: ! 6118: // ! 6119: // Make sure that the interrupt status address doesn't ! 6120: // overlap the controller registers ! 6121: // ! 6122: ! 6123: if (SerialMemCompare( ! 6124: New->InterruptStatus, ! 6125: New->SpanOfInterruptStatus, ! 6126: SerialPhysicalZero, ! 6127: (ULONG)0 ! 6128: ) != AddressesAreEqual) { ! 6129: ! 6130: if (SerialMemCompare( ! 6131: New->InterruptStatus, ! 6132: New->SpanOfInterruptStatus, ! 6133: New->Controller, ! 6134: New->SpanOfController ! 6135: ) != AddressesAreDisjoint) { ! 6136: ! 6137: SerialLogError( ! 6138: DriverObject, ! 6139: NULL, ! 6140: New->Controller, ! 6141: New->InterruptStatus, ! 6142: 0, ! 6143: 0, ! 6144: 0, ! 6145: 45, ! 6146: STATUS_SUCCESS, ! 6147: SERIAL_STATUS_CONTROL_CONFLICT, ! 6148: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6149: New->SymbolicLinkName.Buffer, ! 6150: 0, ! 6151: NULL ! 6152: ); ! 6153: SerialDump( ! 6154: SERERRORS, ! 6155: ("SERIAL: Error in cofig record for %wZ\n" ! 6156: "------- Interrupt status overlaps regular registers\n", ! 6157: &New->NtNameForPort) ! 6158: ); ! 6159: return FALSE; ! 6160: ! 6161: } ! 6162: ! 6163: } ! 6164: ! 6165: // ! 6166: // Loop through all of the old configuration records making ! 6167: // sure that this new record doesn't overlap with any of ! 6168: // the old records. ! 6169: // ! 6170: ! 6171: if (!IsListEmpty(ConfigList)) { ! 6172: ! 6173: PLIST_ENTRY CurrentConfigListEntry = ConfigList->Flink; ! 6174: ! 6175: do { ! 6176: ! 6177: PCONFIG_DATA CurrentSameIntConfig = CONTAINING_RECORD( ! 6178: CurrentConfigListEntry, ! 6179: CONFIG_DATA, ! 6180: ConfigList ! 6181: ); ! 6182: ! 6183: // ! 6184: // We only care about this list if the elements are on the ! 6185: // same bus as this new entry. ! 6186: // ! 6187: ! 6188: if ((CurrentSameIntConfig->InterfaceType == New->InterfaceType) && ! 6189: (CurrentSameIntConfig->AddressSpace == New->AddressSpace) && ! 6190: (CurrentSameIntConfig->BusNumber == New->BusNumber)) { ! 6191: ! 6192: PLIST_ENTRY RootSameIntListEntry = &CurrentSameIntConfig->SameInterrupt; ! 6193: PLIST_ENTRY CurrentSameIntListEntry = RootSameIntListEntry; ! 6194: ! 6195: do { ! 6196: ! 6197: PLIST_ENTRY RootSameStatusListEntry = &CONTAINING_RECORD( ! 6198: CurrentSameIntListEntry, ! 6199: CONFIG_DATA, ! 6200: SameInterrupt ! 6201: )->SameInterruptStatus; ! 6202: PLIST_ENTRY CurrentSameStatusListEntry = RootSameStatusListEntry; ! 6203: ! 6204: do { ! 6205: ! 6206: PCONFIG_DATA OldConfig = CONTAINING_RECORD( ! 6207: CurrentSameStatusListEntry, ! 6208: CONFIG_DATA, ! 6209: SameInterruptStatus ! 6210: ); ! 6211: ! 6212: SerialDump( ! 6213: SERDIAG1, ! 6214: ("SERIAL: Comparing it to %wZ\n" ! 6215: "------- already in the config list\n" ! 6216: "------- PortAddress is %x\n" ! 6217: "------- Interrupt Status is %x\n" ! 6218: "------- BusNumber is %d\n" ! 6219: "------- BusType is %d\n" ! 6220: "------- AddressSpace is %d\n", ! 6221: &OldConfig->NtNameForPort, ! 6222: OldConfig->Controller.LowPart, ! 6223: OldConfig->InterruptStatus.LowPart, ! 6224: OldConfig->BusNumber, ! 6225: OldConfig->InterfaceType, ! 6226: OldConfig->AddressSpace ! 6227: ) ! 6228: ); ! 6229: ! 6230: if (SerialMemCompare( ! 6231: New->Controller, ! 6232: New->SpanOfController, ! 6233: OldConfig->Controller, ! 6234: OldConfig->SpanOfController ! 6235: ) != AddressesAreDisjoint) { ! 6236: ! 6237: SerialLogError( ! 6238: DriverObject, ! 6239: NULL, ! 6240: New->Controller, ! 6241: OldConfig->Controller, ! 6242: 0, ! 6243: 0, ! 6244: 0, ! 6245: 46, ! 6246: STATUS_SUCCESS, ! 6247: SERIAL_CONTROL_OVERLAP, ! 6248: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6249: New->SymbolicLinkName.Buffer, ! 6250: OldConfig->SymbolicLinkName.Length+sizeof(WCHAR), ! 6251: OldConfig->SymbolicLinkName.Buffer ! 6252: ); ! 6253: SerialDump( ! 6254: SERERRORS, ! 6255: ("SERIAL: Error in config record for %wZ\n" ! 6256: "------- Register address overlaps with\n" ! 6257: "------- previous serial device\n", ! 6258: &New->NtNameForPort) ! 6259: ); ! 6260: return FALSE; ! 6261: ! 6262: } ! 6263: ! 6264: // ! 6265: // If we have an interrupt status, make sure that ! 6266: // it doesn't overlap with the old controllers ! 6267: // registers. ! 6268: // ! 6269: ! 6270: if (SerialMemCompare( ! 6271: New->InterruptStatus, ! 6272: New->SpanOfInterruptStatus, ! 6273: SerialPhysicalZero, ! 6274: (ULONG)0 ! 6275: ) != AddressesAreEqual) { ! 6276: ! 6277: if (SerialMemCompare( ! 6278: New->InterruptStatus, ! 6279: New->SpanOfInterruptStatus, ! 6280: OldConfig->Controller, ! 6281: OldConfig->SpanOfController ! 6282: ) != AddressesAreDisjoint) { ! 6283: ! 6284: SerialLogError( ! 6285: DriverObject, ! 6286: NULL, ! 6287: New->Controller, ! 6288: OldConfig->Controller, ! 6289: 0, ! 6290: 0, ! 6291: 0, ! 6292: 47, ! 6293: STATUS_SUCCESS, ! 6294: SERIAL_STATUS_OVERLAP, ! 6295: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6296: New->SymbolicLinkName.Buffer, ! 6297: OldConfig->SymbolicLinkName.Length+sizeof(WCHAR), ! 6298: OldConfig->SymbolicLinkName.Buffer ! 6299: ); ! 6300: SerialDump( ! 6301: SERERRORS, ! 6302: ("SERIAL: Error in config record for %wZ\n" ! 6303: "------- status address overlaps with\n" ! 6304: "------- previous serial device registers\n", ! 6305: &New->NtNameForPort) ! 6306: ); ! 6307: ! 6308: return FALSE; ! 6309: ! 6310: } ! 6311: ! 6312: // ! 6313: // If the old configuration record has an interrupt ! 6314: // status, the addresses should not overlap. ! 6315: // ! 6316: ! 6317: if (SerialMemCompare( ! 6318: OldConfig->InterruptStatus, ! 6319: OldConfig->SpanOfInterruptStatus, ! 6320: SerialPhysicalZero, ! 6321: (ULONG)0 ! 6322: ) != AddressesAreEqual) { ! 6323: ! 6324: if (SerialMemCompare( ! 6325: New->InterruptStatus, ! 6326: New->SpanOfInterruptStatus, ! 6327: OldConfig->InterruptStatus, ! 6328: OldConfig->SpanOfInterruptStatus ! 6329: ) == AddressesOverlap) { ! 6330: ! 6331: SerialLogError( ! 6332: DriverObject, ! 6333: NULL, ! 6334: New->Controller, ! 6335: OldConfig->Controller, ! 6336: 0, ! 6337: 0, ! 6338: 0, ! 6339: 48, ! 6340: STATUS_SUCCESS, ! 6341: SERIAL_STATUS_STATUS_OVERLAP, ! 6342: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6343: New->SymbolicLinkName.Buffer, ! 6344: OldConfig->SymbolicLinkName.Length+sizeof(WCHAR), ! 6345: OldConfig->SymbolicLinkName.Buffer ! 6346: ); ! 6347: SerialDump( ! 6348: SERERRORS, ! 6349: ("SERIAL: Error in config record for %wZ\n" ! 6350: "------- status address overlaps with\n" ! 6351: "------- previous serial status register\n", ! 6352: &New->NtNameForPort) ! 6353: ); ! 6354: ! 6355: return FALSE; ! 6356: ! 6357: } ! 6358: ! 6359: } ! 6360: ! 6361: } ! 6362: ! 6363: // ! 6364: // If the old configuration record has a status ! 6365: // address make sure that it doesn't overlap with ! 6366: // the new controllers address. (Interrupt status ! 6367: // overlap is take care of above. ! 6368: // ! 6369: ! 6370: if (SerialMemCompare( ! 6371: OldConfig->InterruptStatus, ! 6372: OldConfig->SpanOfInterruptStatus, ! 6373: SerialPhysicalZero, ! 6374: (ULONG)0 ! 6375: ) != AddressesAreEqual) { ! 6376: ! 6377: if (SerialMemCompare( ! 6378: New->Controller, ! 6379: New->SpanOfController, ! 6380: OldConfig->InterruptStatus, ! 6381: OldConfig->SpanOfInterruptStatus ! 6382: ) == AddressesOverlap) { ! 6383: ! 6384: SerialLogError( ! 6385: DriverObject, ! 6386: NULL, ! 6387: New->Controller, ! 6388: OldConfig->Controller, ! 6389: 0, ! 6390: 0, ! 6391: 0, ! 6392: 49, ! 6393: STATUS_SUCCESS, ! 6394: SERIAL_CONTROL_STATUS_OVERLAP, ! 6395: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6396: New->SymbolicLinkName.Buffer, ! 6397: OldConfig->SymbolicLinkName.Length+sizeof(WCHAR), ! 6398: OldConfig->SymbolicLinkName.Buffer ! 6399: ); ! 6400: SerialDump( ! 6401: SERERRORS, ! 6402: ("SERIAL: Error in config record for %wZ\n" ! 6403: "------- register address overlaps with\n" ! 6404: "------- previous serial status register\n", ! 6405: &New->NtNameForPort) ! 6406: ); ! 6407: ! 6408: return FALSE; ! 6409: ! 6410: } ! 6411: ! 6412: } ! 6413: ! 6414: CurrentSameStatusListEntry = CurrentSameStatusListEntry->Flink; ! 6415: ! 6416: } while (CurrentSameStatusListEntry != RootSameStatusListEntry); ! 6417: ! 6418: CurrentSameIntListEntry = CurrentSameIntListEntry->Flink; ! 6419: ! 6420: } while (CurrentSameIntListEntry != RootSameIntListEntry); ! 6421: ! 6422: } ! 6423: ! 6424: CurrentConfigListEntry = CurrentConfigListEntry->Flink; ! 6425: ! 6426: } while (CurrentConfigListEntry != ConfigList); ! 6427: } ! 6428: ! 6429: // ! 6430: // If there is an interrupt status then we ! 6431: // loop through the config list again to look ! 6432: // for a config record with the same interrupt ! 6433: // status (on the same bus). ! 6434: // ! 6435: ! 6436: if ((SerialMemCompare( ! 6437: New->InterruptStatus, ! 6438: New->SpanOfInterruptStatus, ! 6439: SerialPhysicalZero, ! 6440: (ULONG)0 ! 6441: ) != AddressesAreEqual) && ! 6442: !IsListEmpty(ConfigList)) { ! 6443: ! 6444: // ! 6445: // We have an interrupt status. Loop through all ! 6446: // previous records, look for an existing interrupt status ! 6447: // the same as the current interrupt status. ! 6448: // ! 6449: ! 6450: PLIST_ENTRY CurrentConfigListEntry = ConfigList->Flink; ! 6451: ! 6452: do { ! 6453: ! 6454: PCONFIG_DATA CurrentSameIntConfig = CONTAINING_RECORD( ! 6455: CurrentConfigListEntry, ! 6456: CONFIG_DATA, ! 6457: ConfigList ! 6458: ); ! 6459: ! 6460: // ! 6461: // We only care about this list if the elements are on the ! 6462: // same bus as this new entry. (There interrupts must therfore ! 6463: // also be the on the same bus. We will check that momentarily). ! 6464: // ! 6465: // We don't check here for the dissimilar interrupts since that ! 6466: // could cause us to miss the error of having the same interrupt ! 6467: // status but different interrupts - which is bizzare. ! 6468: // ! 6469: ! 6470: if ((CurrentSameIntConfig->InterfaceType == New->InterfaceType) && ! 6471: (CurrentSameIntConfig->AddressSpace == New->AddressSpace) && ! 6472: (CurrentSameIntConfig->BusNumber == New->BusNumber)) { ! 6473: ! 6474: PLIST_ENTRY RootSameIntListEntry = &CurrentSameIntConfig->SameInterrupt; ! 6475: PLIST_ENTRY CurrentSameIntListEntry = RootSameIntListEntry; ! 6476: ! 6477: do { ! 6478: ! 6479: PLIST_ENTRY RootSameStatusListEntry = &CONTAINING_RECORD( ! 6480: CurrentSameIntListEntry, ! 6481: CONFIG_DATA, ! 6482: SameInterrupt ! 6483: )->SameInterruptStatus; ! 6484: PLIST_ENTRY CurrentSameStatusListEntry = RootSameStatusListEntry; ! 6485: ! 6486: do { ! 6487: ! 6488: PCONFIG_DATA OldConfig = CONTAINING_RECORD( ! 6489: CurrentSameStatusListEntry, ! 6490: CONFIG_DATA, ! 6491: SameInterruptStatus ! 6492: ); ! 6493: ! 6494: // ! 6495: // If the interrupt status ! 6496: // ! 6497: ! 6498: if (SerialMemCompare( ! 6499: OldConfig->InterruptStatus, ! 6500: OldConfig->SpanOfInterruptStatus, ! 6501: New->InterruptStatus, ! 6502: New->SpanOfInterruptStatus ! 6503: ) == AddressesAreEqual) { ! 6504: ! 6505: // ! 6506: // Same card. Now make sure that they ! 6507: // are using the same interrupt parameters. ! 6508: // ! 6509: ! 6510: if ((New->OriginalIrql != OldConfig->OriginalIrql) || ! 6511: (New->OriginalVector != OldConfig->OriginalVector)) { ! 6512: ! 6513: // ! 6514: // We won't put this into the configuration ! 6515: // list. ! 6516: // ! 6517: ! 6518: SerialLogError( ! 6519: DriverObject, ! 6520: NULL, ! 6521: New->Controller, ! 6522: OldConfig->Controller, ! 6523: 0, ! 6524: 0, ! 6525: 0, ! 6526: 50, ! 6527: STATUS_SUCCESS, ! 6528: SERIAL_MULTI_INTERRUPT_CONFLICT, ! 6529: New->SymbolicLinkName.Length+sizeof(WCHAR), ! 6530: New->SymbolicLinkName.Buffer, ! 6531: OldConfig->SymbolicLinkName.Length+sizeof(WCHAR), ! 6532: OldConfig->SymbolicLinkName.Buffer ! 6533: ); ! 6534: SerialDump( ! 6535: SERERRORS, ! 6536: ("SERIAL: Configuration error for %wZ\n" ! 6537: "------- Same multiport - different interrupts\n", ! 6538: &New->NtNameForPort) ! 6539: ); ! 6540: return FALSE; ! 6541: ! 6542: } ! 6543: ! 6544: // ! 6545: // Place this new record on the SameInterruptStatus ! 6546: // as the old record. ! 6547: // ! 6548: ! 6549: InitializeListHead(&New->SameInterruptStatus); ! 6550: ! 6551: InsertTailList( ! 6552: &OldConfig->SameInterruptStatus, ! 6553: &New->SameInterruptStatus ! 6554: ); ! 6555: ! 6556: return TRUE; ! 6557: ! 6558: } ! 6559: ! 6560: CurrentSameStatusListEntry = CurrentSameStatusListEntry->Flink; ! 6561: ! 6562: } while (CurrentSameStatusListEntry != RootSameStatusListEntry); ! 6563: ! 6564: CurrentSameIntListEntry = CurrentSameIntListEntry->Flink; ! 6565: ! 6566: } while (CurrentSameIntListEntry != RootSameIntListEntry); ! 6567: ! 6568: } ! 6569: ! 6570: CurrentConfigListEntry = CurrentConfigListEntry->Flink; ! 6571: ! 6572: } while (CurrentConfigListEntry != ConfigList); ! 6573: ! 6574: } ! 6575: ! 6576: // ! 6577: // Go through the list again looking for previous devices ! 6578: // with the same interrupt. ! 6579: // ! 6580: ! 6581: if (!IsListEmpty(ConfigList)) { ! 6582: ! 6583: PLIST_ENTRY CurrentConfigListEntry = ConfigList->Flink; ! 6584: ! 6585: do { ! 6586: ! 6587: PCONFIG_DATA OldConfig = CONTAINING_RECORD( ! 6588: CurrentConfigListEntry, ! 6589: CONFIG_DATA, ! 6590: ConfigList ! 6591: ); ! 6592: ! 6593: // ! 6594: // We only care about interrupts that are on ! 6595: // the same bus. ! 6596: // ! 6597: ! 6598: if ((OldConfig->InterfaceType == New->InterfaceType) && ! 6599: (OldConfig->BusNumber == New->BusNumber)) { ! 6600: ! 6601: if ((OldConfig->OriginalIrql == New->OriginalIrql) && ! 6602: (OldConfig->OriginalVector == New->OriginalVector)) { ! 6603: ! 6604: InsertTailList( ! 6605: &OldConfig->SameInterrupt, ! 6606: &New->SameInterrupt ! 6607: ); ! 6608: ! 6609: return TRUE; ! 6610: ! 6611: } ! 6612: ! 6613: } ! 6614: ! 6615: CurrentConfigListEntry = CurrentConfigListEntry->Flink; ! 6616: ! 6617: } while (CurrentConfigListEntry != ConfigList); ! 6618: ! 6619: } ! 6620: ! 6621: // ! 6622: // This port doesn't appear to be sharing with ! 6623: // anything. Just put it on the config list. ! 6624: // ! 6625: ! 6626: InsertTailList( ! 6627: ConfigList, ! 6628: &New->ConfigList ! 6629: ); ! 6630: ! 6631: return TRUE; ! 6632: ! 6633: } ! 6634: ! 6635: PVOID ! 6636: SerialGetMappedAddress( ! 6637: IN INTERFACE_TYPE BusType, ! 6638: IN ULONG BusNumber, ! 6639: PHYSICAL_ADDRESS IoAddress, ! 6640: ULONG NumberOfBytes, ! 6641: ULONG AddressSpace, ! 6642: PBOOLEAN MappedAddress ! 6643: ) ! 6644: ! 6645: /*++ ! 6646: ! 6647: Routine Description: ! 6648: ! 6649: This routine maps an IO address to system address space. ! 6650: ! 6651: Arguments: ! 6652: ! 6653: BusType - what type of bus - eisa, mca, isa ! 6654: IoBusNumber - which IO bus (for machines with multiple buses). ! 6655: IoAddress - base device address to be mapped. ! 6656: NumberOfBytes - number of bytes for which address is valid. ! 6657: AddressSpace - Denotes whether the address is in io space or memory. ! 6658: MappedAddress - indicates whether the address was mapped. ! 6659: This only has meaning if the address returned ! 6660: is non-null. ! 6661: ! 6662: Return Value: ! 6663: ! 6664: Mapped address ! 6665: ! 6666: --*/ ! 6667: ! 6668: { ! 6669: PHYSICAL_ADDRESS cardAddress; ! 6670: PVOID address; ! 6671: ! 6672: HalTranslateBusAddress( ! 6673: BusType, ! 6674: BusNumber, ! 6675: IoAddress, ! 6676: &AddressSpace, ! 6677: &cardAddress ! 6678: ); ! 6679: ! 6680: // ! 6681: // Map the device base address into the virtual address space ! 6682: // if the address is in memory space. ! 6683: // ! 6684: ! 6685: if (!AddressSpace) { ! 6686: ! 6687: address = MmMapIoSpace( ! 6688: cardAddress, ! 6689: NumberOfBytes, ! 6690: FALSE ! 6691: ); ! 6692: ! 6693: *MappedAddress = (BOOLEAN)((address)?(TRUE):(FALSE)); ! 6694: ! 6695: ! 6696: } else { ! 6697: ! 6698: address = (PVOID)cardAddress.LowPart; ! 6699: *MappedAddress = FALSE; ! 6700: ! 6701: } ! 6702: ! 6703: return address; ! 6704: ! 6705: } ! 6706: ! 6707: VOID ! 6708: SerialSetupExternalNaming( ! 6709: IN PSERIAL_DEVICE_EXTENSION Extension ! 6710: ) ! 6711: ! 6712: /*++ ! 6713: ! 6714: Routine Description: ! 6715: ! 6716: This routine will be used to create a symbolic link ! 6717: to the driver name in the given object directory. ! 6718: ! 6719: It will also create an entry in the device map for ! 6720: this device - IF we could create the symbolic link. ! 6721: ! 6722: Arguments: ! 6723: ! 6724: Extension - Pointer to the device extension. ! 6725: ! 6726: Return Value: ! 6727: ! 6728: None. ! 6729: ! 6730: --*/ ! 6731: ! 6732: { ! 6733: ! 6734: UNICODE_STRING fullLinkName; ! 6735: NTSTATUS status; ! 6736: ! 6737: // ! 6738: // Form the full symbolic link name we wish to create. ! 6739: // ! 6740: ! 6741: RtlInitUnicodeString( ! 6742: &fullLinkName, ! 6743: NULL ! 6744: ); ! 6745: ! 6746: // ! 6747: // Allocate some pool for the name. ! 6748: // ! 6749: ! 6750: fullLinkName.MaximumLength = (sizeof(L"\\")*2) + ! 6751: Extension->ObjectDirectory.Length+ ! 6752: Extension->SymbolicLinkName.Length+ ! 6753: sizeof(WCHAR); ! 6754: ! 6755: ! 6756: ! 6757: fullLinkName.Buffer = ExAllocatePool( ! 6758: PagedPool, ! 6759: fullLinkName.MaximumLength ! 6760: ); ! 6761: ! 6762: if (!fullLinkName.Buffer) { ! 6763: ! 6764: // ! 6765: // Couldn't allocate space for the name. ! 6766: // ! 6767: ! 6768: SerialLogError( ! 6769: Extension->DeviceObject->DriverObject, ! 6770: Extension->DeviceObject, ! 6771: Extension->OriginalController, ! 6772: SerialPhysicalZero, ! 6773: 0, ! 6774: 0, ! 6775: 0, ! 6776: 51, ! 6777: STATUS_SUCCESS, ! 6778: SERIAL_INSUFFICIENT_RESOURCES, ! 6779: 0, ! 6780: NULL, ! 6781: 0, ! 6782: NULL ! 6783: ); ! 6784: SerialDump( ! 6785: SERERRORS, ! 6786: ("SERIAL: Couldn't allocate space for the symbolic \n" ! 6787: "------- name for creating the link\n" ! 6788: "------- for port %wZ\n", ! 6789: &Extension->DeviceName) ! 6790: ); ! 6791: ! 6792: } else { ! 6793: ! 6794: RtlZeroMemory( ! 6795: fullLinkName.Buffer, ! 6796: fullLinkName.MaximumLength ! 6797: ); ! 6798: ! 6799: RtlAppendUnicodeToString( ! 6800: &fullLinkName, ! 6801: L"\\" ! 6802: ); ! 6803: ! 6804: RtlAppendUnicodeStringToString( ! 6805: &fullLinkName, ! 6806: &Extension->ObjectDirectory ! 6807: ); ! 6808: ! 6809: RtlAppendUnicodeToString( ! 6810: &fullLinkName, ! 6811: L"\\" ! 6812: ); ! 6813: ! 6814: RtlAppendUnicodeStringToString( ! 6815: &fullLinkName, ! 6816: &Extension->SymbolicLinkName ! 6817: ); ! 6818: ! 6819: ! 6820: status = IoCreateSymbolicLink( ! 6821: &fullLinkName, ! 6822: &Extension->DeviceName ! 6823: ); ! 6824: if (!NT_SUCCESS(status)) { ! 6825: ! 6826: // ! 6827: // Oh well, couldn't create the symbolic link. No point ! 6828: // in trying to create the device map entry. ! 6829: // ! 6830: ! 6831: SerialLogError( ! 6832: Extension->DeviceObject->DriverObject, ! 6833: Extension->DeviceObject, ! 6834: Extension->OriginalController, ! 6835: SerialPhysicalZero, ! 6836: 0, ! 6837: 0, ! 6838: 0, ! 6839: 52, ! 6840: status, ! 6841: SERIAL_NO_SYMLINK_CREATED, ! 6842: Extension->SymbolicLinkName.Length+sizeof(WCHAR), ! 6843: Extension->SymbolicLinkName.Buffer, ! 6844: 0, ! 6845: NULL ! 6846: ); ! 6847: SerialDump( ! 6848: SERERRORS, ! 6849: ("SERIAL: Couldn't create the symbolic link\n" ! 6850: "------- for port %wZ\n", ! 6851: &Extension->DeviceName) ! 6852: ); ! 6853: ! 6854: } else { ! 6855: ! 6856: Extension->CreatedSymbolicLink = TRUE; ! 6857: ! 6858: status = RtlWriteRegistryValue( ! 6859: RTL_REGISTRY_DEVICEMAP, ! 6860: L"SERIALCOMM", ! 6861: Extension->NtNameForPort.Buffer, ! 6862: REG_SZ, ! 6863: Extension->SymbolicLinkName.Buffer, ! 6864: Extension->SymbolicLinkName.Length+sizeof(WCHAR) ! 6865: ); ! 6866: ! 6867: if (!NT_SUCCESS(status)) { ! 6868: ! 6869: SerialLogError( ! 6870: Extension->DeviceObject->DriverObject, ! 6871: Extension->DeviceObject, ! 6872: Extension->OriginalController, ! 6873: SerialPhysicalZero, ! 6874: 0, ! 6875: 0, ! 6876: 0, ! 6877: 53, ! 6878: status, ! 6879: SERIAL_NO_DEVICE_MAP_CREATED, ! 6880: Extension->SymbolicLinkName.Length+sizeof(WCHAR), ! 6881: Extension->SymbolicLinkName.Buffer, ! 6882: 0, ! 6883: NULL ! 6884: ); ! 6885: SerialDump( ! 6886: SERERRORS, ! 6887: ("SERIAL: Couldn't create the device map entry\n" ! 6888: "------- for port %wZ\n", ! 6889: &Extension->DeviceName) ! 6890: ); ! 6891: ! 6892: } ! 6893: ! 6894: } ! 6895: ! 6896: ExFreePool(fullLinkName.Buffer); ! 6897: ! 6898: } ! 6899: ! 6900: } ! 6901: ! 6902: VOID ! 6903: SerialCleanupExternalNaming( ! 6904: IN PSERIAL_DEVICE_EXTENSION Extension ! 6905: ) ! 6906: ! 6907: /*++ ! 6908: ! 6909: Routine Description: ! 6910: ! 6911: This routine will be used to delete a symbolic link ! 6912: to the driver name in the given object directory. ! 6913: ! 6914: It will also delete an entry in the device map for ! 6915: this device if the symbolic link had been created. ! 6916: ! 6917: Arguments: ! 6918: ! 6919: Extension - Pointer to the device extension. ! 6920: ! 6921: Return Value: ! 6922: ! 6923: None. ! 6924: ! 6925: --*/ ! 6926: ! 6927: { ! 6928: ! 6929: UNICODE_STRING fullLinkName; ! 6930: ! 6931: SerialDump( ! 6932: SERDIAG3, ! 6933: ("SERIAL: In SerialCleanupExternalNaming for\n" ! 6934: "------- extension: %x of port %wZ\n", ! 6935: Extension,&Extension->DeviceName) ! 6936: ); ! 6937: ! 6938: // ! 6939: // We're cleaning up here. One reason we're cleaning up ! 6940: // is that we couldn't allocate space for the directory ! 6941: // name or the symbolic link. ! 6942: // ! 6943: ! 6944: if (Extension->ObjectDirectory.Buffer && ! 6945: Extension->SymbolicLinkName.Buffer && ! 6946: Extension->CreatedSymbolicLink) { ! 6947: ! 6948: // ! 6949: // Form the full symbolic link name we wish to create. ! 6950: // ! 6951: ! 6952: RtlInitUnicodeString( ! 6953: &fullLinkName, ! 6954: NULL ! 6955: ); ! 6956: ! 6957: // ! 6958: // Allocate some pool for the name. ! 6959: // ! 6960: ! 6961: fullLinkName.MaximumLength = (sizeof(L"\\")*2) + ! 6962: Extension->ObjectDirectory.Length+ ! 6963: Extension->SymbolicLinkName.Length+ ! 6964: sizeof(WCHAR); ! 6965: ! 6966: fullLinkName.Buffer = ExAllocatePool( ! 6967: PagedPool, ! 6968: fullLinkName.MaximumLength ! 6969: ); ! 6970: ! 6971: if (!fullLinkName.Buffer) { ! 6972: ! 6973: // ! 6974: // Couldn't allocate space for the name. Just go on ! 6975: // to the device map stuff. ! 6976: // ! 6977: ! 6978: SerialLogError( ! 6979: Extension->DeviceObject->DriverObject, ! 6980: Extension->DeviceObject, ! 6981: Extension->OriginalController, ! 6982: SerialPhysicalZero, ! 6983: 0, ! 6984: 0, ! 6985: 0, ! 6986: 54, ! 6987: STATUS_SUCCESS, ! 6988: SERIAL_INSUFFICIENT_RESOURCES, ! 6989: 0, ! 6990: NULL, ! 6991: 0, ! 6992: NULL ! 6993: ); ! 6994: SerialDump( ! 6995: SERERRORS, ! 6996: ("SERIAL: Couldn't allocate space for the symbolic \n" ! 6997: "------- name for creating the link\n" ! 6998: "------- for port %wZ on cleanup\n", ! 6999: &Extension->DeviceName) ! 7000: ); ! 7001: ! 7002: } else { ! 7003: ! 7004: RtlZeroMemory( ! 7005: fullLinkName.Buffer, ! 7006: fullLinkName.MaximumLength ! 7007: ); ! 7008: ! 7009: RtlAppendUnicodeToString( ! 7010: &fullLinkName, ! 7011: L"\\" ! 7012: ); ! 7013: ! 7014: RtlAppendUnicodeStringToString( ! 7015: &fullLinkName, ! 7016: &Extension->ObjectDirectory ! 7017: ); ! 7018: ! 7019: RtlAppendUnicodeToString( ! 7020: &fullLinkName, ! 7021: L"\\" ! 7022: ); ! 7023: ! 7024: RtlAppendUnicodeStringToString( ! 7025: &fullLinkName, ! 7026: &Extension->SymbolicLinkName ! 7027: ); ! 7028: ! 7029: IoDeleteSymbolicLink(&fullLinkName); ! 7030: ! 7031: ExFreePool(fullLinkName.Buffer); ! 7032: ! 7033: } ! 7034: ! 7035: // ! 7036: // We're cleaning up here. One reason we're cleaning up ! 7037: // is that we couldn't allocate space for the NtNameOfPort. ! 7038: // ! 7039: ! 7040: if (Extension->NtNameForPort.Buffer) { ! 7041: ! 7042: NTSTATUS status; ! 7043: ! 7044: status = RtlDeleteRegistryValue( ! 7045: RTL_REGISTRY_DEVICEMAP, ! 7046: L"SERIALCOMM", ! 7047: Extension->NtNameForPort.Buffer ! 7048: ); ! 7049: ! 7050: if (!NT_SUCCESS(status)) { ! 7051: ! 7052: SerialLogError( ! 7053: Extension->DeviceObject->DriverObject, ! 7054: Extension->DeviceObject, ! 7055: Extension->OriginalController, ! 7056: SerialPhysicalZero, ! 7057: 0, ! 7058: 0, ! 7059: 0, ! 7060: 55, ! 7061: status, ! 7062: SERIAL_NO_DEVICE_MAP_DELETED, ! 7063: Extension->SymbolicLinkName.Length+sizeof(WCHAR), ! 7064: Extension->SymbolicLinkName.Buffer, ! 7065: 0, ! 7066: NULL ! 7067: ); ! 7068: SerialDump( ! 7069: SERERRORS, ! 7070: ("SERIAL: Couldn't delete value entry %wZ\n", ! 7071: &Extension->DeviceName) ! 7072: ); ! 7073: ! 7074: } ! 7075: ! 7076: } ! 7077: ! 7078: } ! 7079: ! 7080: } ! 7081: ! 7082: SERIAL_MEM_COMPARES ! 7083: SerialMemCompare( ! 7084: IN PHYSICAL_ADDRESS A, ! 7085: IN ULONG SpanOfA, ! 7086: IN PHYSICAL_ADDRESS B, ! 7087: IN ULONG SpanOfB ! 7088: ) ! 7089: ! 7090: /*++ ! 7091: ! 7092: Routine Description: ! 7093: ! 7094: Compare two phsical address. ! 7095: ! 7096: Arguments: ! 7097: ! 7098: A - One half of the comparison. ! 7099: ! 7100: SpanOfA - In units of bytes, the span of A. ! 7101: ! 7102: B - One half of the comparison. ! 7103: ! 7104: SpanOfB - In units of bytes, the span of B. ! 7105: ! 7106: ! 7107: Return Value: ! 7108: ! 7109: The result of the comparison. ! 7110: ! 7111: --*/ ! 7112: ! 7113: { ! 7114: ! 7115: LARGE_INTEGER a; ! 7116: LARGE_INTEGER b; ! 7117: ! 7118: LARGE_INTEGER lower; ! 7119: ULONG lowerSpan; ! 7120: LARGE_INTEGER higher; ! 7121: ! 7122: a.LowPart = A.LowPart; ! 7123: a.HighPart = A.HighPart; ! 7124: b.LowPart = B.LowPart; ! 7125: b.HighPart = B.HighPart; ! 7126: ! 7127: if (RtlLargeIntegerEqualTo( ! 7128: a, ! 7129: b ! 7130: )) { ! 7131: ! 7132: return AddressesAreEqual; ! 7133: ! 7134: } ! 7135: ! 7136: if (RtlLargeIntegerGreaterThan( ! 7137: a, ! 7138: b ! 7139: )) { ! 7140: ! 7141: higher = a; ! 7142: lower = b; ! 7143: lowerSpan = SpanOfB; ! 7144: ! 7145: } else { ! 7146: ! 7147: higher = b; ! 7148: lower = a; ! 7149: lowerSpan = SpanOfA; ! 7150: ! 7151: } ! 7152: ! 7153: if (RtlLargeIntegerGreaterThanOrEqualTo( ! 7154: RtlLargeIntegerSubtract( ! 7155: higher, ! 7156: lower ! 7157: ), ! 7158: RtlConvertUlongToLargeInteger(lowerSpan) ! 7159: )) { ! 7160: ! 7161: return AddressesAreDisjoint; ! 7162: ! 7163: } ! 7164: ! 7165: return AddressesOverlap; ! 7166: ! 7167: } ! 7168: ! 7169: VOID ! 7170: SerialLogError( ! 7171: IN PDRIVER_OBJECT DriverObject, ! 7172: IN PDEVICE_OBJECT DeviceObject OPTIONAL, ! 7173: IN PHYSICAL_ADDRESS P1, ! 7174: IN PHYSICAL_ADDRESS P2, ! 7175: IN ULONG SequenceNumber, ! 7176: IN UCHAR MajorFunctionCode, ! 7177: IN UCHAR RetryCount, ! 7178: IN ULONG UniqueErrorValue, ! 7179: IN NTSTATUS FinalStatus, ! 7180: IN NTSTATUS SpecificIOStatus, ! 7181: IN ULONG LengthOfInsert1, ! 7182: IN PWCHAR Insert1, ! 7183: IN ULONG LengthOfInsert2, ! 7184: IN PWCHAR Insert2 ! 7185: ) ! 7186: ! 7187: /*++ ! 7188: ! 7189: Routine Description: ! 7190: ! 7191: This routine allocates an error log entry, copies the supplied data ! 7192: to it, and requests that it be written to the error log file. ! 7193: ! 7194: Arguments: ! 7195: ! 7196: DriverObject - A pointer to the driver object for the device. ! 7197: ! 7198: DeviceObject - A pointer to the device object associated with the ! 7199: device that had the error, early in initialization, one may not ! 7200: yet exist. ! 7201: ! 7202: P1,P2 - If phyical addresses for the controller ports involved ! 7203: with the error are available, put them through as dump data. ! 7204: ! 7205: SequenceNumber - A ulong value that is unique to an IRP over the ! 7206: life of the irp in this driver - 0 generally means an error not ! 7207: associated with an irp. ! 7208: ! 7209: MajorFunctionCode - If there is an error associated with the irp, ! 7210: this is the major function code of that irp. ! 7211: ! 7212: RetryCount - The number of times a particular operation has been ! 7213: retried. ! 7214: ! 7215: UniqueErrorValue - A unique long word that identifies the particular ! 7216: call to this function. ! 7217: ! 7218: FinalStatus - The final status given to the irp that was associated ! 7219: with this error. If this log entry is being made during one of ! 7220: the retries this value will be STATUS_SUCCESS. ! 7221: ! 7222: SpecificIOStatus - The IO status for a particular error. ! 7223: ! 7224: LengthOfInsert1 - The length in bytes (including the terminating NULL) ! 7225: of the first insertion string. ! 7226: ! 7227: Insert1 - The first insertion string. ! 7228: ! 7229: LengthOfInsert2 - The length in bytes (including the terminating NULL) ! 7230: of the second insertion string. NOTE, there must ! 7231: be a first insertion string for their to be ! 7232: a second insertion string. ! 7233: ! 7234: Insert2 - The second insertion string. ! 7235: ! 7236: Return Value: ! 7237: ! 7238: None. ! 7239: ! 7240: --*/ ! 7241: ! 7242: { ! 7243: PIO_ERROR_LOG_PACKET errorLogEntry; ! 7244: ! 7245: PVOID objectToUse; ! 7246: SHORT dumpToAllocate = 0; ! 7247: PUCHAR ptrToFirstInsert; ! 7248: PUCHAR ptrToSecondInsert; ! 7249: ! 7250: ! 7251: if (ARGUMENT_PRESENT(DeviceObject)) { ! 7252: ! 7253: objectToUse = DeviceObject; ! 7254: ! 7255: } else { ! 7256: ! 7257: objectToUse = DriverObject; ! 7258: ! 7259: } ! 7260: ! 7261: if (SerialMemCompare( ! 7262: P1, ! 7263: (ULONG)1, ! 7264: SerialPhysicalZero, ! 7265: (ULONG)1 ! 7266: ) != AddressesAreEqual) { ! 7267: ! 7268: dumpToAllocate = (SHORT)sizeof(PHYSICAL_ADDRESS); ! 7269: ! 7270: } ! 7271: ! 7272: if (SerialMemCompare( ! 7273: P2, ! 7274: (ULONG)1, ! 7275: SerialPhysicalZero, ! 7276: (ULONG)1 ! 7277: ) != AddressesAreEqual) { ! 7278: ! 7279: dumpToAllocate += (SHORT)sizeof(PHYSICAL_ADDRESS); ! 7280: ! 7281: } ! 7282: ! 7283: errorLogEntry = IoAllocateErrorLogEntry( ! 7284: objectToUse, ! 7285: (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + ! 7286: dumpToAllocate + LengthOfInsert1 + ! 7287: LengthOfInsert2) ! 7288: ); ! 7289: ! 7290: if ( errorLogEntry != NULL ) { ! 7291: ! 7292: errorLogEntry->ErrorCode = SpecificIOStatus; ! 7293: errorLogEntry->SequenceNumber = SequenceNumber; ! 7294: errorLogEntry->MajorFunctionCode = MajorFunctionCode; ! 7295: errorLogEntry->RetryCount = RetryCount; ! 7296: errorLogEntry->UniqueErrorValue = UniqueErrorValue; ! 7297: errorLogEntry->FinalStatus = FinalStatus; ! 7298: errorLogEntry->DumpDataSize = dumpToAllocate; ! 7299: ! 7300: if (dumpToAllocate) { ! 7301: ! 7302: RtlCopyMemory( ! 7303: &errorLogEntry->DumpData[0], ! 7304: &P1, ! 7305: sizeof(PHYSICAL_ADDRESS) ! 7306: ); ! 7307: ! 7308: if (dumpToAllocate > sizeof(PHYSICAL_ADDRESS)) { ! 7309: ! 7310: RtlCopyMemory( ! 7311: ((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS), ! 7312: &P2, ! 7313: sizeof(PHYSICAL_ADDRESS) ! 7314: ); ! 7315: ! 7316: ptrToFirstInsert = ! 7317: ((PUCHAR)&errorLogEntry->DumpData[0])+(2*sizeof(PHYSICAL_ADDRESS)); ! 7318: ! 7319: } else { ! 7320: ! 7321: ptrToFirstInsert = ! 7322: ((PUCHAR)&errorLogEntry->DumpData[0])+sizeof(PHYSICAL_ADDRESS); ! 7323: ! 7324: ! 7325: } ! 7326: ! 7327: } else { ! 7328: ! 7329: ptrToFirstInsert = (PUCHAR)&errorLogEntry->DumpData[0]; ! 7330: ! 7331: } ! 7332: ! 7333: ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1; ! 7334: ! 7335: if (LengthOfInsert1) { ! 7336: ! 7337: errorLogEntry->NumberOfStrings = 1; ! 7338: errorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert - ! 7339: (PUCHAR)errorLogEntry); ! 7340: RtlCopyMemory( ! 7341: ptrToFirstInsert, ! 7342: Insert1, ! 7343: LengthOfInsert1 ! 7344: ); ! 7345: ! 7346: if (LengthOfInsert2) { ! 7347: ! 7348: errorLogEntry->NumberOfStrings = 2; ! 7349: RtlCopyMemory( ! 7350: ptrToSecondInsert, ! 7351: Insert2, ! 7352: LengthOfInsert2 ! 7353: ); ! 7354: ! 7355: } ! 7356: ! 7357: } ! 7358: ! 7359: IoWriteErrorLogEntry(errorLogEntry); ! 7360: ! 7361: } ! 7362: ! 7363: } ! 7364: ! 7365: VOID ! 7366: SerialUnReportResourcesDevice( ! 7367: IN PSERIAL_DEVICE_EXTENSION Extension ! 7368: ) ! 7369: ! 7370: /*++ ! 7371: ! 7372: Routine Description: ! 7373: ! 7374: This routine *un*reports the resources used for a device that ! 7375: is "ready" to run. If some conflict was detected, it doesn't ! 7376: matter, the reources are *un*reported. ! 7377: ! 7378: Arguments: ! 7379: ! 7380: Extension - The device extension of the device we are *un*reporting ! 7381: resources for. ! 7382: ! 7383: Return Value: ! 7384: ! 7385: None. ! 7386: ! 7387: --*/ ! 7388: ! 7389: { ! 7390: ! 7391: CM_RESOURCE_LIST resourceList; ! 7392: ULONG sizeOfResourceList = 0; ! 7393: UNICODE_STRING className; ! 7394: BOOLEAN junkBoolean; ! 7395: ! 7396: SerialDump( ! 7397: SERDIAG3, ! 7398: ("SERIAL: In SerialUnreportResourcesDevice\n" ! 7399: "------- for extension %x of port %wZ\n", ! 7400: Extension,&Extension->DeviceName) ! 7401: ); ! 7402: RtlZeroMemory( ! 7403: &resourceList, ! 7404: sizeof(CM_RESOURCE_LIST) ! 7405: ); ! 7406: ! 7407: resourceList.Count = 0; ! 7408: ! 7409: RtlInitUnicodeString( ! 7410: &className, ! 7411: L"LOADED SERIAL DRIVER RESOURCES" ! 7412: ); ! 7413: ! 7414: IoReportResourceUsage( ! 7415: &className, ! 7416: Extension->DeviceObject->DriverObject, ! 7417: NULL, ! 7418: 0, ! 7419: Extension->DeviceObject, ! 7420: &resourceList, ! 7421: sizeof(CM_RESOURCE_LIST), ! 7422: FALSE, ! 7423: &junkBoolean ! 7424: ); ! 7425: ! 7426: } ! 7427: ! 7428: VOID ! 7429: SerialReportResourcesDevice( ! 7430: IN PSERIAL_DEVICE_EXTENSION Extension, ! 7431: OUT BOOLEAN *ConflictDetected ! 7432: ) ! 7433: ! 7434: /*++ ! 7435: ! 7436: Routine Description: ! 7437: ! 7438: This routine reports the resources used for a device that ! 7439: is "ready" to run. If some conflict was detected, it doesn't ! 7440: matter, the reources are reported. ! 7441: ! 7442: Arguments: ! 7443: ! 7444: Extension - The device extension of the device we are reporting ! 7445: resources for. ! 7446: ! 7447: ConflictDetected - Pointer to a boolean that we will pass ! 7448: to the resource reporting code. ! 7449: ! 7450: Return Value: ! 7451: ! 7452: None. ! 7453: ! 7454: --*/ ! 7455: ! 7456: { ! 7457: ! 7458: PCM_RESOURCE_LIST resourceList; ! 7459: ULONG sizeOfResourceList; ! 7460: ULONG countOfPartials; ! 7461: PCM_PARTIAL_RESOURCE_DESCRIPTOR partial; ! 7462: UNICODE_STRING className; ! 7463: ! 7464: SerialDump( ! 7465: SERDIAG3, ! 7466: ("SERIAL: In SerialReportResourcesDevice\n" ! 7467: "------- for extension %x of port %wZ\n", ! 7468: Extension,&Extension->DeviceName) ! 7469: ); ! 7470: ! 7471: // ! 7472: // The resource list for a device will consist of ! 7473: // ! 7474: // The resource list record itself with a count ! 7475: // of one for the single "built in" full resource ! 7476: // descriptor. ! 7477: // ! 7478: // The built-in full resource descriptor will contain ! 7479: // the bus type and busnumber and the built in partial ! 7480: // resource list. ! 7481: // ! 7482: // The built in partial resource list will have at ! 7483: // least a count of 2: ! 7484: // ! 7485: // 1) The interrupt that this device will be ! 7486: // coming in on. ! 7487: // ! 7488: // 2) The base register physical address and it's span. ! 7489: // ! 7490: // The built in partial resource list will have a ! 7491: // count of 3 if it has an interrupt status address ! 7492: // That interrupt status address will consist of ! 7493: // the physical address and the span (normally 1). ! 7494: // ! 7495: ! 7496: countOfPartials = Extension->InterruptStatus?3:2; ! 7497: sizeOfResourceList = sizeof(CM_RESOURCE_LIST) + ! 7498: (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)* ! 7499: (countOfPartials-1)); ! 7500: ! 7501: resourceList = ExAllocatePool( ! 7502: PagedPool, ! 7503: sizeOfResourceList ! 7504: ); ! 7505: ! 7506: if (!resourceList) { ! 7507: ! 7508: // ! 7509: // Oh well, can't allocate the memory. Act as though ! 7510: // we succeeded. ! 7511: // ! 7512: ! 7513: SerialLogError( ! 7514: Extension->DeviceObject->DriverObject, ! 7515: Extension->DeviceObject, ! 7516: Extension->OriginalController, ! 7517: SerialPhysicalZero, ! 7518: 0, ! 7519: 0, ! 7520: 0, ! 7521: 56, ! 7522: STATUS_SUCCESS, ! 7523: SERIAL_INSUFFICIENT_RESOURCES, ! 7524: 0, ! 7525: NULL, ! 7526: 0, ! 7527: NULL ! 7528: ); ! 7529: return; ! 7530: ! 7531: } ! 7532: ! 7533: RtlZeroMemory( ! 7534: resourceList, ! 7535: sizeOfResourceList ! 7536: ); ! 7537: ! 7538: resourceList->Count = 1; ! 7539: ! 7540: ! 7541: resourceList->List[0].InterfaceType = Extension->InterfaceType; ! 7542: resourceList->List[0].BusNumber = Extension->BusNumber; ! 7543: resourceList->List[0].PartialResourceList.Count = countOfPartials; ! 7544: partial = &resourceList->List[0].PartialResourceList.PartialDescriptors[0]; ! 7545: ! 7546: // ! 7547: // Account for the space used by the controller. ! 7548: // ! 7549: ! 7550: partial->Type = CmResourceTypePort; ! 7551: partial->ShareDisposition = CmResourceShareDeviceExclusive; ! 7552: partial->Flags = (USHORT)Extension->AddressSpace; ! 7553: partial->u.Port.Start = Extension->OriginalController; ! 7554: partial->u.Port.Length = Extension->SpanOfController; ! 7555: ! 7556: partial++; ! 7557: ! 7558: // ! 7559: // Report the interrupt information. ! 7560: // ! 7561: ! 7562: partial->Type = CmResourceTypeInterrupt; ! 7563: ! 7564: if (Extension->InterruptShareable) { ! 7565: ! 7566: partial->ShareDisposition = CmResourceShareShared; ! 7567: ! 7568: } else { ! 7569: ! 7570: partial->ShareDisposition = CmResourceShareDriverExclusive; ! 7571: ! 7572: } ! 7573: ! 7574: if (Extension->InterruptMode == Latched) { ! 7575: ! 7576: partial->Flags = CM_RESOURCE_INTERRUPT_LATCHED; ! 7577: ! 7578: } else { ! 7579: ! 7580: partial->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; ! 7581: ! 7582: } ! 7583: ! 7584: partial->u.Interrupt.Vector = Extension->OriginalVector; ! 7585: partial->u.Interrupt.Level = Extension->OriginalIrql; ! 7586: ! 7587: // ! 7588: // We have an interrupt status register. Report it. ! 7589: // ! 7590: ! 7591: if (countOfPartials == 3) { ! 7592: ! 7593: partial++; ! 7594: ! 7595: partial->Type = CmResourceTypePort; ! 7596: partial->ShareDisposition = CmResourceShareDriverExclusive; ! 7597: partial->Flags = (USHORT)Extension->AddressSpace; ! 7598: partial->u.Port.Start = Extension->OriginalInterruptStatus; ! 7599: partial->u.Port.Length = Extension->SpanOfInterruptStatus; ! 7600: ! 7601: } ! 7602: ! 7603: RtlInitUnicodeString( ! 7604: &className, ! 7605: L"LOADED SERIAL DRIVER RESOURCES" ! 7606: ); ! 7607: ! 7608: IoReportResourceUsage( ! 7609: &className, ! 7610: Extension->DeviceObject->DriverObject, ! 7611: NULL, ! 7612: 0, ! 7613: Extension->DeviceObject, ! 7614: resourceList, ! 7615: sizeOfResourceList, ! 7616: FALSE, ! 7617: ConflictDetected ! 7618: ); ! 7619: ! 7620: ExFreePool(resourceList); ! 7621: ! 7622: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.