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

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