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

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:             &paramTable[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 = &notThereDefault;
        !           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 = &notThereDefault;
        !           363:         paramTable[3].DefaultLength = sizeof(ULONG);
        !           364: 
        !           365:         if (!NT_SUCCESS(RtlQueryRegistryValues(
        !           366:                             RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
        !           367:                             path,
        !           368:                             &paramTable[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(&currentConfig->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:                      &currentConfig->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:                      &currentConfig->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(&currentConfig->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:                      &currentConfig->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:                      &currentConfig->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(&currentConfig->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:                          &currentConfig->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:                          &currentConfig->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:              &currentConfig->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:         &parametersPath,
        !          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:         &parametersPath,
        !          4798:         RegistryPath
        !          4799:         );
        !          4800:     RtlAppendUnicodeToString(
        !          4801:         &parametersPath,
        !          4802:         L"\\"
        !          4803:         );
        !          4804:     RtlAppendUnicodeToString(
        !          4805:         &parametersPath,
        !          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:              &parametersPath)
        !          4837:             );
        !          4838: 
        !          4839:         goto DoFirmwareAdd;
        !          4840: 
        !          4841:     }
        !          4842: 
        !          4843:     //
        !          4844:     // Open the key given by our registry path & Parameters.
        !          4845:     //
        !          4846: 
        !          4847:     InitializeObjectAttributes(
        !          4848:         &parametersAttributes,
        !          4849:         &parametersPath,
        !          4850:         OBJ_CASE_INSENSITIVE,
        !          4851:         NULL,
        !          4852:         NULL
        !          4853:         );
        !          4854: 
        !          4855:     if (!NT_SUCCESS(ZwOpenKey(
        !          4856:                        &parametersKey,
        !          4857:                        MAXIMUM_ALLOWED,
        !          4858:                        &parametersAttributes
        !          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: }

unix.superglobalmegacorp.com

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