Annotation of ntddk/src/video/miniport/cirrus/cirrus.c, revision 1.1

1.1     ! root        1: //---------------------------------------------------------------------------
        !             2: /*++
        !             3: 
        !             4: Copyright (c) 1992  Microsoft Corporation
        !             5: 
        !             6: Module Name:
        !             7: 
        !             8:     cirrus.c
        !             9: 
        !            10: Abstract:
        !            11: 
        !            12:     This is the miniport driver for the Cirrus Logic 6410/6420/542x VGA's.
        !            13: 
        !            14: Environment:
        !            15: 
        !            16:     kernel mode only
        !            17: 
        !            18: Notes:
        !            19: 
        !            20: Revision History:
        !            21: 
        !            22: --*/
        !            23: //---------------------------------------------------------------------------
        !            24: 
        !            25: #include "dderror.h"
        !            26: #include "devioctl.h"
        !            27: #include "miniport.h"
        !            28: 
        !            29: #include "ntddvdeo.h"
        !            30: #include "video.h"
        !            31: #include "cirrus.h"
        !            32: #include "cl_data.h"
        !            33: 
        !            34: //---------------------------------------------------------------------------
        !            35: //
        !            36: // Function declarations
        !            37: //
        !            38: // Functions that start with 'VGA' are entry points for the OS port driver.
        !            39: //
        !            40: 
        !            41: VP_STATUS
        !            42: VgaFindAdapter(
        !            43:     PVOID HwDeviceExtension,
        !            44:     PVOID HwContext,
        !            45:     PWSTR ArgumentString,
        !            46:     PVIDEO_PORT_CONFIG_INFO ConfigInfo,
        !            47:     PUCHAR Again
        !            48:     );
        !            49: 
        !            50: BOOLEAN
        !            51: VgaInitialize(
        !            52:     PVOID HwDeviceExtension
        !            53:     );
        !            54: 
        !            55: BOOLEAN
        !            56: VgaStartIO(
        !            57:     PVOID HwDeviceExtension,
        !            58:     PVIDEO_REQUEST_PACKET RequestPacket
        !            59:     );
        !            60: 
        !            61: //
        !            62: // Private function prototypes.
        !            63: //
        !            64: 
        !            65: VP_STATUS
        !            66: VgaQueryAvailableModes(
        !            67:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !            68:     PVIDEO_MODE_INFORMATION ModeInformation,
        !            69:     ULONG ModeInformationSize,
        !            70:     PULONG OutputSize
        !            71:     );
        !            72: 
        !            73: VP_STATUS
        !            74: VgaQueryNumberOfAvailableModes(
        !            75:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !            76:     PVIDEO_NUM_MODES NumModes,
        !            77:     ULONG NumModesSize,
        !            78:     PULONG OutputSize
        !            79:     );
        !            80: 
        !            81: VP_STATUS
        !            82: VgaQueryCurrentMode(
        !            83:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !            84:     PVIDEO_MODE_INFORMATION ModeInformation,
        !            85:     ULONG ModeInformationSize,
        !            86:     PULONG OutputSize
        !            87:     );
        !            88: 
        !            89: VP_STATUS
        !            90: VgaSetMode(
        !            91:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !            92:     PVIDEO_MODE Mode,
        !            93:     ULONG ModeSize
        !            94:     );
        !            95: 
        !            96: VP_STATUS
        !            97: VgaLoadAndSetFont(
        !            98:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !            99:     PVIDEO_LOAD_FONT_INFORMATION FontInformation,
        !           100:     ULONG FontInformationSize
        !           101:     );
        !           102: 
        !           103: VP_STATUS
        !           104: VgaQueryCursorPosition(
        !           105:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           106:     PVIDEO_CURSOR_POSITION CursorPosition,
        !           107:     ULONG CursorPositionSize,
        !           108:     PULONG OutputSize
        !           109:     );
        !           110: 
        !           111: VP_STATUS
        !           112: VgaSetCursorPosition(
        !           113:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           114:     PVIDEO_CURSOR_POSITION CursorPosition,
        !           115:     ULONG CursorPositionSize
        !           116:     );
        !           117: 
        !           118: VP_STATUS
        !           119: VgaQueryCursorAttributes(
        !           120:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           121:     PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
        !           122:     ULONG CursorAttributesSize,
        !           123:     PULONG OutputSize
        !           124:     );
        !           125: 
        !           126: VP_STATUS
        !           127: VgaSetCursorAttributes(
        !           128:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           129:     PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
        !           130:     ULONG CursorAttributesSize
        !           131:     );
        !           132: 
        !           133: BOOLEAN
        !           134: VgaIsPresent(
        !           135:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !           136:     );
        !           137: 
        !           138: BOOLEAN
        !           139: CirrusLogicIsPresent(
        !           140:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !           141:     );
        !           142: 
        !           143: ULONG
        !           144: CirrusFindVmemSize(
        !           145:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !           146:     );
        !           147: 
        !           148: VOID
        !           149: CirrusValidateModes(
        !           150:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !           151:     );
        !           152: 
        !           153: VOID
        !           154: SetCirrusBanking(
        !           155:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           156:     USHORT BankNumber
        !           157:     );
        !           158: 
        !           159: USHORT
        !           160: CirrusFind6410DisplayType(
        !           161:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !           162:     );
        !           163: 
        !           164: BOOLEAN
        !           165: CirrusFind6340(
        !           166:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !           167:     );
        !           168: 
        !           169: VOID
        !           170: VgaInterpretCmdStream(
        !           171:     PVOID HwDeviceExtension,
        !           172:     PUSHORT pusCmdStream
        !           173:     );
        !           174: 
        !           175: VP_STATUS
        !           176: VgaSetPaletteReg(
        !           177:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           178:     PVIDEO_PALETTE_DATA PaletteBuffer,
        !           179:     ULONG PaletteBufferSize
        !           180:     );
        !           181: 
        !           182: VP_STATUS
        !           183: VgaSetColorLookup(
        !           184:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           185:     PVIDEO_CLUT ClutBuffer,
        !           186:     ULONG ClutBufferSize
        !           187:     );
        !           188: 
        !           189: VP_STATUS
        !           190: VgaRestoreHardwareState(
        !           191:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           192:     PVIDEO_HARDWARE_STATE HardwareState,
        !           193:     ULONG HardwareStateSize
        !           194:     );
        !           195: 
        !           196: VP_STATUS
        !           197: VgaSaveHardwareState(
        !           198:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           199:     PVIDEO_HARDWARE_STATE HardwareState,
        !           200:     ULONG HardwareStateSize,
        !           201:     PULONG OutputSize
        !           202:     );
        !           203: 
        !           204: VP_STATUS
        !           205: VgaGetBankSelectCode(
        !           206:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           207:     PVIDEO_BANK_SELECT BankSelect,
        !           208:     ULONG BankSelectSize,
        !           209:     PULONG OutputSize
        !           210:     );
        !           211: 
        !           212: 
        !           213: //---------------------------------------------------------------------------
        !           214: ULONG
        !           215: DriverEntry(
        !           216:     PVOID Context1,
        !           217:     PVOID Context2
        !           218:     )
        !           219: 
        !           220: /*++
        !           221: 
        !           222: Routine Description:
        !           223: 
        !           224:     Installable driver initialization entry point.
        !           225:     This entry point is called directly by the I/O system.
        !           226: 
        !           227: Arguments:
        !           228: 
        !           229:     Context1 - First context value passed by the operating system. This is
        !           230:         the value with which the miniport driver calls VideoPortInitialize().
        !           231: 
        !           232:     Context2 - Second context value passed by the operating system. This is
        !           233:         the value with which the miniport driver calls VideoPortInitialize().
        !           234: 
        !           235: Return Value:
        !           236: 
        !           237:     Status from VideoPortInitialize()
        !           238: 
        !           239: --*/
        !           240: 
        !           241: {
        !           242: 
        !           243:     VIDEO_HW_INITIALIZATION_DATA hwInitData;
        !           244:     ULONG status;
        !           245:     ULONG initializationStatus;
        !           246: 
        !           247:     //
        !           248:     // Zero out structure.
        !           249:     //
        !           250: 
        !           251:     VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA));
        !           252: 
        !           253:     //
        !           254:     // Specify sizes of structure and extension.
        !           255:     //
        !           256: 
        !           257:     hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA);
        !           258: 
        !           259:     //
        !           260:     // Set entry points.
        !           261:     //
        !           262: 
        !           263:     hwInitData.HwFindAdapter = VgaFindAdapter;
        !           264:     hwInitData.HwInitialize = VgaInitialize;
        !           265:     hwInitData.HwInterrupt = NULL;
        !           266:     hwInitData.HwStartIO = VgaStartIO;
        !           267: 
        !           268:     //
        !           269:     // Determine the size we require for the device extension.
        !           270:     //
        !           271: 
        !           272:     hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
        !           273: 
        !           274:     //
        !           275:     // Always start with parameters for device0 in this case.
        !           276:     // We can leave it like this since we know we will only ever find one
        !           277:     // VGA type adapter in a machine.
        !           278:     //
        !           279: 
        !           280: //    hwInitData.StartingDeviceNumber = 0;
        !           281: 
        !           282:     //
        !           283:     // Once all the relevant information has been stored, call the video
        !           284:     // port driver to do the initialization.
        !           285:     // For this device we will repeat this call three times, for ISA, EISA
        !           286:     // and MCA.
        !           287:     // We will return the minimum of all return values.
        !           288:     //
        !           289: 
        !           290:     hwInitData.AdapterInterfaceType = Isa;
        !           291: 
        !           292:     initializationStatus = VideoPortInitialize(Context1,
        !           293:                                                Context2,
        !           294:                                                &hwInitData,
        !           295:                                                NULL);
        !           296: 
        !           297:     hwInitData.AdapterInterfaceType = Eisa;
        !           298: 
        !           299:     status = VideoPortInitialize(Context1,
        !           300:                                  Context2,
        !           301:                                  &hwInitData,
        !           302:                                  NULL);
        !           303: 
        !           304:     if (initializationStatus > status) {
        !           305:         initializationStatus = status;
        !           306:     }
        !           307: 
        !           308:     hwInitData.AdapterInterfaceType = MicroChannel;
        !           309: 
        !           310:     status = VideoPortInitialize(Context1,
        !           311:                                  Context2,
        !           312:                                  &hwInitData,
        !           313:                                  NULL);
        !           314: 
        !           315:     if (initializationStatus > status) {
        !           316:         initializationStatus = status;
        !           317:     }
        !           318: 
        !           319:     return initializationStatus;
        !           320: 
        !           321: } // end DriverEntry()
        !           322: 
        !           323: //---------------------------------------------------------------------------
        !           324: VP_STATUS
        !           325: VgaFindAdapter(
        !           326:     PVOID HwDeviceExtension,
        !           327:     PVOID HwContext,
        !           328:     PWSTR ArgumentString,
        !           329:     PVIDEO_PORT_CONFIG_INFO ConfigInfo,
        !           330:     PUCHAR Again
        !           331:     )
        !           332: 
        !           333: /*++
        !           334: 
        !           335: Routine Description:
        !           336: 
        !           337:     This routine is called to determine if the adapter for this driver
        !           338:     is present in the system.
        !           339:     If it is present, the function fills out some information describing
        !           340:     the adapter.
        !           341: 
        !           342: Arguments:
        !           343: 
        !           344:     HwDeviceExtension - Supplies the miniport driver's adapter storage. This
        !           345:         storage is initialized to zero before this call.
        !           346: 
        !           347:     HwContext - Supplies the context value which was passed to
        !           348:         VideoPortInitialize().
        !           349: 
        !           350:     ArgumentString - Supplies a NULL terminated ASCII string. This string
        !           351:         originates from the user.
        !           352: 
        !           353:     ConfigInfo - Returns the configuration information structure which is
        !           354:         filled by the miniport driver. This structure is initialized with
        !           355:         any known configuration information (such as SystemIoBusNumber) by
        !           356:         the port driver. Where possible, drivers should have one set of
        !           357:         defaults which do not require any supplied configuration information.
        !           358: 
        !           359:     Again - Indicates if the miniport driver wants the port driver to call
        !           360:         its VIDEO_HW_FIND_ADAPTER function again with a new device extension
        !           361:         and the same config info. This is used by the miniport drivers which
        !           362:         can search for several adapters on a bus.
        !           363: 
        !           364: Return Value:
        !           365: 
        !           366:     This routine must return:
        !           367: 
        !           368:     NO_ERROR - Indicates a host adapter was found and the
        !           369:         configuration information was successfully determined.
        !           370: 
        !           371:     ERROR_INVALID_PARAMETER - Indicates an adapter was found but there was an
        !           372:         error obtaining the configuration information. If possible an error
        !           373:         should be logged.
        !           374: 
        !           375:     ERROR_DEV_NOT_EXIST - Indicates no host adapter was found for the
        !           376:         supplied configuration information.
        !           377: 
        !           378: --*/
        !           379: 
        !           380: {
        !           381: 
        !           382:     PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
        !           383:     VP_STATUS status;
        !           384: 
        !           385:     //
        !           386:     // Make sure the size of the structure is at least as large as what we
        !           387:     // are expecting (check version of the config info structure).
        !           388:     //
        !           389: 
        !           390:     if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) {
        !           391: 
        !           392:         return ERROR_INVALID_PARAMETER;
        !           393: 
        !           394:     }
        !           395: 
        !           396:     //
        !           397:     // No interrupt information is necessary.
        !           398:     //
        !           399: 
        !           400:     //
        !           401:     // Check to see if there is a hardware resource conflict.
        !           402:     //
        !           403: 
        !           404:     status = VideoPortVerifyAccessRanges(HwDeviceExtension,
        !           405:                                          NUM_VGA_ACCESS_RANGES,
        !           406:                                          VgaAccessRange);
        !           407: 
        !           408:     if (status != NO_ERROR) {
        !           409: 
        !           410:         return status;
        !           411: 
        !           412:     }
        !           413: 
        !           414:     //
        !           415:     // Get logical IO port addresses.
        !           416:     //
        !           417: 
        !           418:     if ( (hwDeviceExtension->IOAddress =
        !           419:               VideoPortGetDeviceBase(hwDeviceExtension,
        !           420:                                      VgaAccessRange->RangeStart,
        !           421:                                      VGA_MAX_IO_PORT - VGA_BASE_IO_PORT + 1,
        !           422:                                      TRUE)) == NULL) {
        !           423: 
        !           424:         VideoDebugPrint((2, "VgaFindAdapter - Fail to get io address\n"));
        !           425: 
        !           426:         return ERROR_INVALID_PARAMETER;
        !           427: 
        !           428:     }
        !           429: 
        !           430:     //
        !           431:     // Determine whether a VGA is present.
        !           432:     //
        !           433: 
        !           434:     if (!VgaIsPresent(hwDeviceExtension)) {
        !           435: 
        !           436:         return ERROR_DEV_NOT_EXIST;
        !           437: 
        !           438:     }
        !           439: 
        !           440:     //
        !           441:     // Pass a pointer to the emulator range we are using.
        !           442:     //
        !           443: 
        !           444:     ConfigInfo->NumEmulatorAccessEntries = VGA_NUM_EMULATOR_ACCESS_ENTRIES;
        !           445:     ConfigInfo->EmulatorAccessEntries = VgaEmulatorAccessEntries;
        !           446:     ConfigInfo->EmulatorAccessEntriesContext = (ULONG) hwDeviceExtension;
        !           447: 
        !           448:     ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = MEM_VGA;
        !           449:     ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0x00000000;
        !           450:     ConfigInfo->VdmPhysicalVideoMemoryLength = MEM_VGA_SIZE;
        !           451: 
        !           452:     //
        !           453:     // Minimum size of the buffer required to store the hardware state
        !           454:     // information returned by IOCTL_VIDEO_SAVE_HARDWARE_STATE.
        !           455:     //
        !           456: 
        !           457:     ConfigInfo->HardwareStateSize = VGA_TOTAL_STATE_SIZE;
        !           458: 
        !           459:     //
        !           460:     // Video memory information
        !           461:     //
        !           462: 
        !           463:     hwDeviceExtension->PhysicalVideoMemoryBase.HighPart = 0x00000000;
        !           464:     hwDeviceExtension->PhysicalVideoMemoryBase.LowPart = MEM_VGA;
        !           465:     hwDeviceExtension->PhysicalVideoMemoryLength = MEM_VGA_SIZE;
        !           466: 
        !           467:     //
        !           468:     // Map the video memory into the system virtual address space so we can
        !           469:     // clear it out and use it for save and restore.
        !           470:     //
        !           471: 
        !           472:     if ( (hwDeviceExtension->VideoMemoryAddress =
        !           473:               VideoPortGetDeviceBase(hwDeviceExtension,
        !           474:                       hwDeviceExtension->PhysicalVideoMemoryBase,
        !           475:               hwDeviceExtension->PhysicalVideoMemoryLength, FALSE)) == NULL) {
        !           476: 
        !           477:         VideoDebugPrint((1, "VgaFindAdapter - Fail to get memory address\n"));
        !           478: 
        !           479:         return ERROR_INVALID_PARAMETER;
        !           480: 
        !           481:     }
        !           482: // 
        !           483: // now that we have the video memory address in portected mode, lets do
        !           484: // the required video card initialization. We will try to detect a Cirrus 
        !           485: // Logic chipset...
        !           486: //
        !           487:     //
        !           488:     // Determine whether an CL6410/6420/542x is present.
        !           489:     //
        !           490: 
        !           491:     if (!CirrusLogicIsPresent(hwDeviceExtension)) {
        !           492: 
        !           493:         return ERROR_DEV_NOT_EXIST;
        !           494: 
        !           495:     }
        !           496: 
        !           497:     //
        !           498:     // Indicate we do not wish to be called again for another initialization.
        !           499:     //
        !           500: 
        !           501:     *Again = 0;
        !           502: 
        !           503:     //
        !           504:     // Indicate a successful completion status.
        !           505:     //
        !           506: 
        !           507:     return NO_ERROR;
        !           508: 
        !           509: } // VgaFindAdapter()
        !           510: 
        !           511: //---------------------------------------------------------------------------
        !           512: BOOLEAN
        !           513: VgaInitialize(
        !           514:     PVOID HwDeviceExtension
        !           515:     )
        !           516: 
        !           517: /*++
        !           518: 
        !           519: Routine Description:
        !           520: 
        !           521:     This routine does one time initialization of the device.
        !           522: 
        !           523: Arguments:
        !           524: 
        !           525:     HwDeviceExtension - Pointer to the miniport driver's adapter information.
        !           526: 
        !           527: Return Value:
        !           528: 
        !           529:     None.
        !           530: 
        !           531: --*/
        !           532: 
        !           533: {
        !           534:     PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
        !           535: 
        !           536:     //
        !           537:     // set up the default cursor position and type.
        !           538:     //
        !           539: 
        !           540:     hwDeviceExtension->CursorPosition.Column = 0;
        !           541:     hwDeviceExtension->CursorPosition.Row = 0;
        !           542:     hwDeviceExtension->CursorTopScanLine = 0;
        !           543:     hwDeviceExtension->CursorBottomScanLine = 31;
        !           544:     hwDeviceExtension->CursorEnable = TRUE;
        !           545: 
        !           546:     return TRUE;
        !           547: 
        !           548: } // VgaInitialize()
        !           549: 
        !           550: //---------------------------------------------------------------------------
        !           551: BOOLEAN
        !           552: VgaStartIO(
        !           553:     PVOID HwDeviceExtension,
        !           554:     PVIDEO_REQUEST_PACKET RequestPacket
        !           555:     )
        !           556: 
        !           557: /*++
        !           558: 
        !           559: Routine Description:
        !           560: 
        !           561:     This routine is the main execution routine for the miniport driver. It
        !           562:     accepts a Video Request Packet, performs the request, and then returns
        !           563:     with the appropriate status.
        !           564: 
        !           565: Arguments:
        !           566: 
        !           567:     HwDeviceExtension - Pointer to the miniport driver's adapter information.
        !           568: 
        !           569:     RequestPacket - Pointer to the video request packet. This structure
        !           570:         contains all the parameters passed to the VideoIoControl function.
        !           571: 
        !           572: Return Value:
        !           573: 
        !           574:     This routine will return error codes from the various support routines
        !           575:     and will also return ERROR_INSUFFICIENT_BUFFER for incorrectly sized
        !           576:     buffers and ERROR_INVALID_FUNCTION for unsupported functions.
        !           577: 
        !           578: --*/
        !           579: 
        !           580: {
        !           581:     PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
        !           582:     VP_STATUS status;
        !           583:     VIDEO_MODE videoMode;
        !           584:     PVIDEO_MEMORY_INFORMATION memoryInformation;
        !           585:     ULONG inIoSpace;
        !           586: 
        !           587:     //
        !           588:     // Switch on the IoContolCode in the RequestPacket. It indicates which
        !           589:     // function must be performed by the driver.
        !           590:     //
        !           591: 
        !           592:     switch (RequestPacket->IoControlCode) {
        !           593: 
        !           594: 
        !           595:     case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
        !           596: 
        !           597:         VideoDebugPrint((2, "VgaStartIO - MapVideoMemory\n"));
        !           598: 
        !           599:         if ( (RequestPacket->OutputBufferLength <
        !           600:               (RequestPacket->StatusBlock->Information =
        !           601:                                      sizeof(VIDEO_MEMORY_INFORMATION))) ||
        !           602:              (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {
        !           603: 
        !           604:             status = ERROR_INSUFFICIENT_BUFFER;
        !           605:         }
        !           606: 
        !           607:         memoryInformation = RequestPacket->OutputBuffer;
        !           608: 
        !           609:         memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
        !           610:                 (RequestPacket->InputBuffer))->RequestedVirtualAddress;
        !           611: 
        !           612:         memoryInformation->VideoRamLength =
        !           613:                 hwDeviceExtension->PhysicalVideoMemoryLength;
        !           614: 
        !           615:         inIoSpace = 0;
        !           616: 
        !           617:         status = VideoPortMapMemory(hwDeviceExtension,
        !           618:                                     hwDeviceExtension->PhysicalVideoMemoryBase,
        !           619:                                     &(memoryInformation->VideoRamLength),
        !           620:                                     &inIoSpace,
        !           621:                                     &(memoryInformation->VideoRamBase));
        !           622: 
        !           623:         memoryInformation->FrameBufferBase =
        !           624:         ((PUCHAR) (memoryInformation->VideoRamBase)) +
        !           625:             (hwDeviceExtension->PhysicalFrameBase.LowPart -
        !           626:             hwDeviceExtension->PhysicalVideoMemoryBase.LowPart);
        !           627: 
        !           628:         memoryInformation->FrameBufferLength =
        !           629:             hwDeviceExtension->PhysicalFrameLength;
        !           630: 
        !           631:         break;
        !           632: 
        !           633: 
        !           634:     case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
        !           635: 
        !           636:         VideoDebugPrint((2, "VgaStartIO - UnMapVideoMemory\n"));
        !           637: 
        !           638:         if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) {
        !           639: 
        !           640:             status = ERROR_INSUFFICIENT_BUFFER;
        !           641:         }
        !           642: 
        !           643:         status = VideoPortUnmapMemory(hwDeviceExtension,
        !           644:                                       ((PVIDEO_MEMORY)
        !           645:                                        (RequestPacket->InputBuffer))->
        !           646:                                            RequestedVirtualAddress,
        !           647:                                       0);
        !           648: 
        !           649:         break;
        !           650: 
        !           651: 
        !           652:     case IOCTL_VIDEO_QUERY_AVAIL_MODES:
        !           653: 
        !           654:         VideoDebugPrint((2, "VgaStartIO - QueryAvailableModes\n"));
        !           655: 
        !           656:         status = VgaQueryAvailableModes(HwDeviceExtension,
        !           657:                                         (PVIDEO_MODE_INFORMATION)
        !           658:                                             RequestPacket->OutputBuffer,
        !           659:                                         RequestPacket->OutputBufferLength,
        !           660:                                         &RequestPacket->StatusBlock->Information);
        !           661: 
        !           662:         break;
        !           663: 
        !           664: 
        !           665:     case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
        !           666: 
        !           667:         VideoDebugPrint((2, "VgaStartIO - QueryNumAvailableModes\n"));
        !           668: 
        !           669:         status = VgaQueryNumberOfAvailableModes(HwDeviceExtension,
        !           670:                                                 (PVIDEO_NUM_MODES)
        !           671:                                                     RequestPacket->OutputBuffer,
        !           672:                                                 RequestPacket->OutputBufferLength,
        !           673:                                                 &RequestPacket->StatusBlock->Information);
        !           674: 
        !           675:         break;
        !           676: 
        !           677: 
        !           678:     case IOCTL_VIDEO_QUERY_CURRENT_MODE:
        !           679: 
        !           680:         VideoDebugPrint((2, "VgaStartIO - QueryCurrentMode\n"));
        !           681: 
        !           682:         status = VgaQueryCurrentMode(HwDeviceExtension,
        !           683:                                      (PVIDEO_MODE_INFORMATION) RequestPacket->OutputBuffer,
        !           684:                                      RequestPacket->OutputBufferLength,
        !           685:                                      &RequestPacket->StatusBlock->Information);
        !           686: 
        !           687:         break;
        !           688: 
        !           689: 
        !           690:     case IOCTL_VIDEO_SET_CURRENT_MODE:
        !           691: 
        !           692:         VideoDebugPrint((2, "VgaStartIO - SetCurrentModes\n"));
        !           693: 
        !           694:         status = VgaSetMode(HwDeviceExtension,
        !           695:                               (PVIDEO_MODE) RequestPacket->InputBuffer,
        !           696:                               RequestPacket->InputBufferLength);
        !           697: 
        !           698:         break;
        !           699: 
        !           700: 
        !           701:     case IOCTL_VIDEO_RESET_DEVICE:
        !           702: 
        !           703:         VideoDebugPrint((2, "VgaStartIO - Reset Device\n"));
        !           704: 
        !           705:         videoMode.RequestedMode = DEFAULT_MODE;
        !           706: 
        !           707:         status = VgaSetMode(HwDeviceExtension,
        !           708:                                  (PVIDEO_MODE) &videoMode,
        !           709:                                  sizeof(videoMode));
        !           710: 
        !           711:         break;
        !           712: 
        !           713: 
        !           714:     case IOCTL_VIDEO_LOAD_AND_SET_FONT:
        !           715: 
        !           716:         VideoDebugPrint((2, "VgaStartIO - LoadAndSetFont\n"));
        !           717: 
        !           718:         status = VgaLoadAndSetFont(HwDeviceExtension,
        !           719:                                    (PVIDEO_LOAD_FONT_INFORMATION) RequestPacket->InputBuffer,
        !           720:                                    RequestPacket->InputBufferLength);
        !           721: 
        !           722:         break;
        !           723: 
        !           724: 
        !           725:     case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
        !           726: 
        !           727:         VideoDebugPrint((2, "VgaStartIO - QueryCursorPosition\n"));
        !           728: 
        !           729:         status = VgaQueryCursorPosition(HwDeviceExtension,
        !           730:                                         (PVIDEO_CURSOR_POSITION) RequestPacket->OutputBuffer,
        !           731:                                         RequestPacket->OutputBufferLength,
        !           732:                                         &RequestPacket->StatusBlock->Information);
        !           733: 
        !           734:         break;
        !           735: 
        !           736: 
        !           737:     case IOCTL_VIDEO_SET_CURSOR_POSITION:
        !           738: 
        !           739:         VideoDebugPrint((2, "VgaStartIO - SetCursorPosition\n"));
        !           740: 
        !           741:         status = VgaSetCursorPosition(HwDeviceExtension,
        !           742:                                       (PVIDEO_CURSOR_POSITION)
        !           743:                                           RequestPacket->InputBuffer,
        !           744:                                       RequestPacket->InputBufferLength);
        !           745: 
        !           746:         break;
        !           747: 
        !           748: 
        !           749:     case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
        !           750: 
        !           751:         VideoDebugPrint((2, "VgaStartIO - QueryCursorAttributes\n"));
        !           752: 
        !           753:         status = VgaQueryCursorAttributes(HwDeviceExtension,
        !           754:                                           (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->OutputBuffer,
        !           755:                                           RequestPacket->OutputBufferLength,
        !           756:                                           &RequestPacket->StatusBlock->Information);
        !           757: 
        !           758:         break;
        !           759: 
        !           760: 
        !           761:     case IOCTL_VIDEO_SET_CURSOR_ATTR:
        !           762: 
        !           763:         VideoDebugPrint((2, "VgaStartIO - SetCursorAttributes\n"));
        !           764: 
        !           765:         status = VgaSetCursorAttributes(HwDeviceExtension,
        !           766:                                         (PVIDEO_CURSOR_ATTRIBUTES) RequestPacket->InputBuffer,
        !           767:                                         RequestPacket->InputBufferLength);
        !           768: 
        !           769:         break;
        !           770: 
        !           771: 
        !           772:     case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
        !           773: 
        !           774:         VideoDebugPrint((2, "VgaStartIO - SetPaletteRegs\n"));
        !           775: 
        !           776:         status = VgaSetPaletteReg(HwDeviceExtension,
        !           777:                                   (PVIDEO_PALETTE_DATA) RequestPacket->InputBuffer,
        !           778:                                   RequestPacket->InputBufferLength);
        !           779: 
        !           780:         break;
        !           781: 
        !           782: 
        !           783:     case IOCTL_VIDEO_SET_COLOR_REGISTERS:
        !           784: 
        !           785:         VideoDebugPrint((2, "VgaStartIO - SetColorRegs\n"));
        !           786: 
        !           787:         status = VgaSetColorLookup(HwDeviceExtension,
        !           788:                                    (PVIDEO_CLUT) RequestPacket->InputBuffer,
        !           789:                                    RequestPacket->InputBufferLength);
        !           790: 
        !           791:         break;
        !           792: 
        !           793: 
        !           794:     case IOCTL_VIDEO_ENABLE_VDM:
        !           795: 
        !           796:         VideoDebugPrint((2, "VgaStartIO - EnableVDM\n"));
        !           797: 
        !           798:         hwDeviceExtension->TrappedValidatorCount = 0;
        !           799:         hwDeviceExtension->SequencerAddressValue = 0;
        !           800: 
        !           801:         hwDeviceExtension->CurrentNumVdmAccessRanges =
        !           802:             NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE;
        !           803:         hwDeviceExtension->CurrentVdmAccessRange =
        !           804:             MinimalVgaValidatorAccessRange;
        !           805: 
        !           806:         VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
        !           807:                                          hwDeviceExtension->CurrentNumVdmAccessRanges,
        !           808:                                          hwDeviceExtension->CurrentVdmAccessRange);
        !           809: 
        !           810:         status = NO_ERROR;
        !           811: 
        !           812:         break;
        !           813: 
        !           814: 
        !           815:     case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
        !           816: 
        !           817:         VideoDebugPrint((2, "VgaStartIO - RestoreHardwareState\n"));
        !           818: 
        !           819:         status = VgaRestoreHardwareState(HwDeviceExtension,
        !           820:                                          (PVIDEO_HARDWARE_STATE) RequestPacket->InputBuffer,
        !           821:                                          RequestPacket->InputBufferLength);
        !           822: 
        !           823:         break;
        !           824: 
        !           825: 
        !           826:     case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
        !           827: 
        !           828:         VideoDebugPrint((2, "VgaStartIO - SaveHardwareState\n"));
        !           829: 
        !           830:         status = VgaSaveHardwareState(HwDeviceExtension,
        !           831:                                       (PVIDEO_HARDWARE_STATE) RequestPacket->OutputBuffer,
        !           832:                                       RequestPacket->OutputBufferLength,
        !           833:                                       &RequestPacket->StatusBlock->Information);
        !           834: 
        !           835:         break;
        !           836: 
        !           837:     case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
        !           838: 
        !           839:         VideoDebugPrint((2, "VgaStartIO - GetBankSelectCode\n"));
        !           840: 
        !           841:         status = VgaGetBankSelectCode(HwDeviceExtension,
        !           842:                                         (PVIDEO_BANK_SELECT) RequestPacket->OutputBuffer,
        !           843:                                         RequestPacket->OutputBufferLength,
        !           844:                                         &RequestPacket->StatusBlock->Information);
        !           845: 
        !           846:         VideoDebugPrint((2, "VgaStartIO - END GetBankSelectCode\n"));
        !           847:         break;
        !           848: 
        !           849: 
        !           850:     //
        !           851:     // if we get here, an invalid IoControlCode was specified.
        !           852:     //
        !           853: 
        !           854:     default:
        !           855: 
        !           856:         VideoDebugPrint((1, "Fell through vga startIO routine - invalid command\n"));
        !           857: 
        !           858:         status = ERROR_INVALID_FUNCTION;
        !           859: 
        !           860:         break;
        !           861: 
        !           862:     }
        !           863: 
        !           864:     RequestPacket->StatusBlock->Status = status;
        !           865: 
        !           866:     return TRUE;
        !           867: 
        !           868: } // VgaStartIO()
        !           869: 
        !           870: //---------------------------------------------------------------------------
        !           871: //
        !           872: // private routines
        !           873: //
        !           874: 
        !           875: VP_STATUS
        !           876: VgaLoadAndSetFont(
        !           877:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !           878:     PVIDEO_LOAD_FONT_INFORMATION FontInformation,
        !           879:     ULONG FontInformationSize
        !           880:     )
        !           881: 
        !           882: /*++
        !           883: 
        !           884: Routine Description:
        !           885: 
        !           886:     Takes a buffer containing a user-defined font and loads it into the
        !           887:     VGA soft font memory and programs the VGA to the appropriate character
        !           888:     cell size.
        !           889: 
        !           890: Arguments:
        !           891: 
        !           892:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !           893: 
        !           894:     FontInformation - Pointer to the structure containing the information
        !           895:         about the loadable ROM font to be set.
        !           896: 
        !           897:     FontInformationSize - Length of the input buffer supplied by the user.
        !           898: 
        !           899: Return Value:
        !           900: 
        !           901:     NO_ERROR - information returned successfully
        !           902: 
        !           903:     ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
        !           904: 
        !           905:     ERROR_INVALID_PARAMETER - invalid video mode
        !           906: 
        !           907: --*/
        !           908: 
        !           909: {
        !           910:     PUCHAR destination;
        !           911:     PUCHAR source;
        !           912:     USHORT width;
        !           913:     ULONG i;
        !           914: 
        !           915:     //
        !           916:     // Text mode only; If we are in a graphics mode, return an error
        !           917:     //
        !           918: 
        !           919:     if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
        !           920: 
        !           921:         return ERROR_INVALID_PARAMETER;
        !           922: 
        !           923:     }
        !           924: 
        !           925:     //
        !           926:     // Check if the size of the data in the input buffer is large enough
        !           927:     // and that it contains all the data.
        !           928:     //
        !           929: 
        !           930:     if ( (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION)) ||
        !           931:          (FontInformationSize < sizeof(VIDEO_LOAD_FONT_INFORMATION) +
        !           932:                         sizeof(UCHAR) * (FontInformation->FontSize - 1)) ) {
        !           933: 
        !           934:         return ERROR_INSUFFICIENT_BUFFER;
        !           935: 
        !           936:     }
        !           937: 
        !           938:     //
        !           939:     // Check for the width and height of the font
        !           940:     //
        !           941: 
        !           942:     if ( ((FontInformation->WidthInPixels != 8) &&
        !           943:           (FontInformation->WidthInPixels != 9)) ||
        !           944:          (FontInformation->HeightInPixels > 32) ) {
        !           945: 
        !           946:         return ERROR_INVALID_PARAMETER;
        !           947: 
        !           948:     }
        !           949: 
        !           950:     //
        !           951:     // Check the size of the font buffer is the right size for the size
        !           952:     // font being passed down.
        !           953:     //
        !           954: 
        !           955:     if (FontInformation->FontSize < FontInformation->HeightInPixels * 256 *
        !           956:                                     sizeof(UCHAR) ) {
        !           957: 
        !           958:         return ERROR_INSUFFICIENT_BUFFER;
        !           959: 
        !           960:     }
        !           961: 
        !           962:     //
        !           963:     // Since the font parameters are valid, store the parameters in the
        !           964:     // device extension and load the font.
        !           965:     //
        !           966: 
        !           967:     HwDeviceExtension->FontPelRows = FontInformation->HeightInPixels;
        !           968:     HwDeviceExtension->FontPelColumns = FontInformation->WidthInPixels;
        !           969: 
        !           970:     HwDeviceExtension->CurrentMode->row =
        !           971:         HwDeviceExtension->CurrentMode->vres / HwDeviceExtension->FontPelRows;
        !           972: 
        !           973:     width =
        !           974:       HwDeviceExtension->CurrentMode->hres / HwDeviceExtension->FontPelColumns;
        !           975: 
        !           976:     if (width < (USHORT)HwDeviceExtension->CurrentMode->col) {
        !           977: 
        !           978:         HwDeviceExtension->CurrentMode->col = width;
        !           979: 
        !           980:     }
        !           981: 
        !           982:     source = &(FontInformation->Font[0]);
        !           983: 
        !           984:     //
        !           985:     // Set up the destination and source pointers for the font
        !           986:     //
        !           987: 
        !           988:     destination = (PUCHAR)HwDeviceExtension->VideoMemoryAddress;
        !           989: 
        !           990:     //
        !           991:     // Map font buffer at A0000
        !           992:     //
        !           993: 
        !           994:     VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
        !           995: 
        !           996:     //
        !           997:     // Move the font to its destination
        !           998:     //
        !           999: 
        !          1000:     for (i = 1; i <= 256; i++) {
        !          1001: 
        !          1002:         VideoPortWriteRegisterBufferUchar(destination,
        !          1003:                                           source,
        !          1004:                                           FontInformation->HeightInPixels);
        !          1005: 
        !          1006:         destination += 32;
        !          1007:         source += FontInformation->HeightInPixels;
        !          1008: 
        !          1009:     }
        !          1010: 
        !          1011:     VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
        !          1012: 
        !          1013:     //
        !          1014:     // Restore to a text mode.
        !          1015:     //
        !          1016: 
        !          1017:     //
        !          1018:     // Set Height of font.
        !          1019:     //
        !          1020: 
        !          1021:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1022:             CRTC_ADDRESS_PORT_COLOR, 0x9);
        !          1023:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1024:             CRTC_DATA_PORT_COLOR,
        !          1025:             (UCHAR)(FontInformation->HeightInPixels - 1));
        !          1026: 
        !          1027:     //
        !          1028:     // Set Width of font.
        !          1029:     //
        !          1030: 
        !          1031:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1032:             CRTC_ADDRESS_PORT_COLOR, 0x12);
        !          1033:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1034:             CRTC_DATA_PORT_COLOR,
        !          1035:             (UCHAR)(((USHORT)FontInformation->HeightInPixels *
        !          1036:             (USHORT)HwDeviceExtension->CurrentMode->row) - 1));
        !          1037: 
        !          1038:     i = HwDeviceExtension->CurrentMode->vres /
        !          1039:         HwDeviceExtension->CurrentMode->row;
        !          1040: 
        !          1041:     //
        !          1042:     // Set Cursor End
        !          1043:     //
        !          1044: 
        !          1045:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1046:             CRTC_ADDRESS_PORT_COLOR, 0xb);
        !          1047:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1048:             CRTC_DATA_PORT_COLOR, (UCHAR)--i);
        !          1049: 
        !          1050:     //
        !          1051:     // Set Cursor Statr
        !          1052:     //
        !          1053: 
        !          1054:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1055:             CRTC_ADDRESS_PORT_COLOR, 0xa);
        !          1056:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1057:             CRTC_DATA_PORT_COLOR, (UCHAR)--i);
        !          1058: 
        !          1059:     return NO_ERROR;
        !          1060: 
        !          1061: } //end VgaLoadAndSetFont()
        !          1062: 
        !          1063: //---------------------------------------------------------------------------
        !          1064: VP_STATUS
        !          1065: VgaQueryCursorPosition(
        !          1066:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          1067:     PVIDEO_CURSOR_POSITION CursorPosition,
        !          1068:     ULONG CursorPositionSize,
        !          1069:     PULONG OutputSize
        !          1070:     )
        !          1071: 
        !          1072: /*++
        !          1073: 
        !          1074: Routine Description:
        !          1075: 
        !          1076:     This routine returns the row and column of the cursor.
        !          1077: 
        !          1078: Arguments:
        !          1079: 
        !          1080:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          1081: 
        !          1082:     CursorPosition - Pointer to the output buffer supplied by the user. This
        !          1083:         is where the cursor position is stored.
        !          1084: 
        !          1085:     CursorPositionSize - Length of the output buffer supplied by the user.
        !          1086: 
        !          1087:     OutputSize - Pointer to a buffer in which to return the actual size of
        !          1088:         the data in the buffer. If the buffer was not large enough, this
        !          1089:         contains the minimum required buffer size.
        !          1090: 
        !          1091: Return Value:
        !          1092: 
        !          1093:     NO_ERROR - information returned successfully
        !          1094: 
        !          1095:     ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
        !          1096:         any useful data
        !          1097: 
        !          1098:     ERROR_INVALID_PARAMETER - invalid video mode
        !          1099: 
        !          1100: --*/
        !          1101: 
        !          1102: {
        !          1103:     //
        !          1104:     // Text mode only; If we are in a graphics mode, return an error
        !          1105:     //
        !          1106: 
        !          1107:     if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
        !          1108: 
        !          1109:         *OutputSize = 0;
        !          1110:         return ERROR_INVALID_PARAMETER;
        !          1111: 
        !          1112:     }
        !          1113: 
        !          1114:     //
        !          1115:     // If the buffer passed in is not large enough return an
        !          1116:     // appropriate error code.
        !          1117:     //
        !          1118: 
        !          1119:     if (CursorPositionSize < (*OutputSize = sizeof(VIDEO_CURSOR_POSITION)) ) {
        !          1120: 
        !          1121:         *OutputSize = 0;
        !          1122:         return ERROR_INSUFFICIENT_BUFFER;
        !          1123: 
        !          1124:     }
        !          1125: 
        !          1126:     //
        !          1127:     // Store the postition of the cursor into the buffer.
        !          1128:     //
        !          1129: 
        !          1130:     CursorPosition->Column = HwDeviceExtension->CursorPosition.Column;
        !          1131:     CursorPosition->Row = HwDeviceExtension->CursorPosition.Row;
        !          1132: 
        !          1133:     return NO_ERROR;
        !          1134: 
        !          1135: } // end VgaQueryCursorPosition()
        !          1136: 
        !          1137: //---------------------------------------------------------------------------
        !          1138: VP_STATUS
        !          1139: VgaSetCursorPosition(
        !          1140:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          1141:     PVIDEO_CURSOR_POSITION CursorPosition,
        !          1142:     ULONG CursorPositionSize
        !          1143:     )
        !          1144: 
        !          1145: /*++
        !          1146: 
        !          1147: Routine Description:
        !          1148: 
        !          1149:     This routine verifies that the requested cursor position is within
        !          1150:     the row and column bounds of the current mode and font. If valid, then
        !          1151:     it sets the row and column of the cursor.
        !          1152: 
        !          1153: Arguments:
        !          1154: 
        !          1155:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          1156: 
        !          1157:     CursorPosition - Pointer to the structure containing the cursor position.
        !          1158: 
        !          1159:     CursorPositionSize - Length of the input buffer supplied by the user.
        !          1160: 
        !          1161: Return Value:
        !          1162: 
        !          1163:     NO_ERROR - information returned successfully
        !          1164: 
        !          1165:     ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
        !          1166: 
        !          1167:     ERROR_INVALID_PARAMETER - invalid video mode
        !          1168: 
        !          1169: --*/
        !          1170: 
        !          1171: {
        !          1172:     USHORT position;
        !          1173: 
        !          1174:     //
        !          1175:     // Text mode only; If we are in a graphics mode, return an error
        !          1176:     //
        !          1177: 
        !          1178:     if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
        !          1179: 
        !          1180:         return ERROR_INVALID_PARAMETER;
        !          1181: 
        !          1182:     }
        !          1183: 
        !          1184:     //
        !          1185:     // Check if the size of the data in the input buffer is large enough.
        !          1186:     //
        !          1187: 
        !          1188:     if (CursorPositionSize < sizeof(VIDEO_CURSOR_POSITION)) {
        !          1189: 
        !          1190:             return ERROR_INSUFFICIENT_BUFFER;
        !          1191: 
        !          1192:     }
        !          1193: 
        !          1194:     //
        !          1195:     // Check if the new values for the cursor positions are in the valid
        !          1196:     // bounds for the screen.
        !          1197:     //
        !          1198: 
        !          1199:     if ((CursorPosition->Column >= HwDeviceExtension->CurrentMode->col) ||
        !          1200:         (CursorPosition->Row >= HwDeviceExtension->CurrentMode->row)) {
        !          1201: 
        !          1202:         return ERROR_INVALID_PARAMETER;
        !          1203: 
        !          1204:     }
        !          1205: 
        !          1206:     //
        !          1207:     // Store these new values in the device extension so we can use them in
        !          1208:     // a QUERY.
        !          1209:     //
        !          1210: 
        !          1211:     HwDeviceExtension->CursorPosition.Column = CursorPosition->Column;
        !          1212:     HwDeviceExtension->CursorPosition.Row = CursorPosition->Row;
        !          1213: 
        !          1214:     //
        !          1215:     // Calculate the position on the screen at which the cursor must be
        !          1216:     // be displayed
        !          1217:     //
        !          1218: 
        !          1219:     position = (USHORT) (HwDeviceExtension->CurrentMode->col *
        !          1220:                          CursorPosition->Row + CursorPosition->Column);
        !          1221: 
        !          1222: 
        !          1223:     //
        !          1224:     // Address Cursor Location Low Register in CRT Controller Registers
        !          1225:     //
        !          1226: 
        !          1227:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1228:             CRTC_ADDRESS_PORT_COLOR, IND_CURSOR_LOW_LOC);
        !          1229: 
        !          1230:     //
        !          1231:     // Set Cursor Location Low Register
        !          1232:     //
        !          1233: 
        !          1234:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1235:             CRTC_DATA_PORT_COLOR, (UCHAR) (position & 0x00FF));
        !          1236: 
        !          1237:     //
        !          1238:     // Address Cursor Location High Register in CRT Controller Registers
        !          1239:     //
        !          1240: 
        !          1241:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1242:             CRTC_ADDRESS_PORT_COLOR, IND_CURSOR_HIGH_LOC);
        !          1243: 
        !          1244:     //
        !          1245:     // Set Cursor Location High Register
        !          1246:     //
        !          1247: 
        !          1248:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1249:             CRTC_DATA_PORT_COLOR, (UCHAR) (position >> 8));
        !          1250: 
        !          1251:     return NO_ERROR;
        !          1252: 
        !          1253: } // end VgaSetCursorPosition()
        !          1254: 
        !          1255: //---------------------------------------------------------------------------
        !          1256: VP_STATUS
        !          1257: VgaQueryCursorAttributes(
        !          1258:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          1259:     PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
        !          1260:     ULONG CursorAttributesSize,
        !          1261:     PULONG OutputSize
        !          1262:     )
        !          1263: 
        !          1264: /*++
        !          1265: 
        !          1266: Routine Description:
        !          1267: 
        !          1268:     This routine returns information about the height and visibility of the
        !          1269:     cursor.
        !          1270: 
        !          1271: Arguments:
        !          1272: 
        !          1273:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          1274: 
        !          1275:     CursorAttributes - Pointer to the output buffer supplied by the user.
        !          1276:         This is where the cursor type is stored.
        !          1277: 
        !          1278:     CursorAttributesSize - Length of the output buffer supplied by the user.
        !          1279: 
        !          1280:     OutputSize - Pointer to a buffer in which to return the actual size of
        !          1281:         the data in the buffer. If the buffer was not large enough, this
        !          1282:         contains the minimum required buffer size.
        !          1283: 
        !          1284: Return Value:
        !          1285: 
        !          1286:     NO_ERROR - information returned successfully
        !          1287: 
        !          1288:     ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
        !          1289:         any useful data
        !          1290: 
        !          1291:     ERROR_INVALID_PARAMETER - invalid video mode
        !          1292: 
        !          1293: --*/
        !          1294: 
        !          1295: {
        !          1296:     //
        !          1297:     // Text mode only; If we are in a graphics mode, return an error
        !          1298:     //
        !          1299: 
        !          1300:     if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
        !          1301: 
        !          1302:         *OutputSize = 0;
        !          1303:         return ERROR_INVALID_PARAMETER;
        !          1304: 
        !          1305:     }
        !          1306: 
        !          1307:     //
        !          1308:     // Find out the size of the data to be put in the the buffer and return
        !          1309:     // that in the status information (whether or not the information is
        !          1310:     // there). If the buffer passed in is not large enough return an
        !          1311:     // appropriate error code.
        !          1312:     //
        !          1313: 
        !          1314:     if (CursorAttributesSize < (*OutputSize =
        !          1315:             sizeof(VIDEO_CURSOR_ATTRIBUTES)) ) {
        !          1316: 
        !          1317:         *OutputSize = 0;
        !          1318:         return ERROR_INSUFFICIENT_BUFFER;
        !          1319: 
        !          1320:     }
        !          1321: 
        !          1322:     //
        !          1323:     // Store the cursor information into the buffer.
        !          1324:     //
        !          1325: 
        !          1326:     CursorAttributes->Height = (USHORT) HwDeviceExtension->CursorTopScanLine;
        !          1327:     CursorAttributes->Width = (USHORT) HwDeviceExtension->CursorBottomScanLine;
        !          1328:     CursorAttributes->Enable = HwDeviceExtension->CursorEnable;
        !          1329: 
        !          1330:     return NO_ERROR;
        !          1331: 
        !          1332: } // end VgaQueryCursorAttributes()
        !          1333: 
        !          1334: //---------------------------------------------------------------------------
        !          1335: VP_STATUS
        !          1336: VgaSetCursorAttributes(
        !          1337:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          1338:     PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
        !          1339:     ULONG CursorAttributesSize
        !          1340:     )
        !          1341: 
        !          1342: /*++
        !          1343: 
        !          1344: Routine Description:
        !          1345: 
        !          1346:     This routine verifies that the requested cursor height is within the
        !          1347:     bounds of the character cell. If valid, then it sets the new
        !          1348:     visibility and height of the cursor.
        !          1349: 
        !          1350: Arguments:
        !          1351: 
        !          1352:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          1353: 
        !          1354:     CursorType - Pointer to the structure containing the cursor information.
        !          1355: 
        !          1356:     CursorTypeSize - Length of the input buffer supplied by the user.
        !          1357: 
        !          1358: Return Value:
        !          1359: 
        !          1360:     NO_ERROR - information returned successfully
        !          1361: 
        !          1362:     ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data
        !          1363: 
        !          1364:     ERROR_INVALID_PARAMETER - invalid video mode
        !          1365: 
        !          1366: --*/
        !          1367: 
        !          1368: {
        !          1369:     UCHAR cursorLine;
        !          1370: 
        !          1371:     //
        !          1372:     // Text mode only; If we are in a graphics mode, return an error
        !          1373:     //
        !          1374: 
        !          1375:     if (HwDeviceExtension->CurrentMode->fbType & VIDEO_MODE_GRAPHICS) {
        !          1376: 
        !          1377:         return ERROR_INVALID_PARAMETER;
        !          1378: 
        !          1379:     }
        !          1380: 
        !          1381:     //
        !          1382:     // Check if the size of the data in the input buffer is large enough.
        !          1383:     //
        !          1384: 
        !          1385:     if (CursorAttributesSize < sizeof(VIDEO_CURSOR_ATTRIBUTES)) {
        !          1386: 
        !          1387:             return ERROR_INSUFFICIENT_BUFFER;
        !          1388: 
        !          1389:     }
        !          1390: 
        !          1391:     //
        !          1392:     // Check if the new values for the cursor type are in the valid range.
        !          1393:     //
        !          1394: 
        !          1395:     if ((CursorAttributes->Height >= HwDeviceExtension->FontPelRows) ||
        !          1396:         (CursorAttributes->Width > 31)) {
        !          1397: 
        !          1398:         return ERROR_INVALID_PARAMETER;
        !          1399: 
        !          1400:     }
        !          1401: 
        !          1402:     //
        !          1403:     // Store the cursor information in the device extension so we can use
        !          1404:     // them in a QUERY.
        !          1405:     //
        !          1406: 
        !          1407:     HwDeviceExtension->CursorTopScanLine = (UCHAR) CursorAttributes->Height;
        !          1408:     HwDeviceExtension->CursorBottomScanLine = (UCHAR) CursorAttributes->Width;
        !          1409:     HwDeviceExtension->CursorEnable = CursorAttributes->Enable;
        !          1410: 
        !          1411:     //
        !          1412:     // Address Cursor Start Register in CRT Controller Registers
        !          1413:     //
        !          1414: 
        !          1415:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1416:                                 CRTC_ADDRESS_PORT_COLOR,
        !          1417:                             IND_CURSOR_START);
        !          1418: 
        !          1419:     //
        !          1420:     // Set Cursor Start Register by writting to CRTCtl Data Register
        !          1421:     // Preserve the high three bits of this register.
        !          1422:     //
        !          1423:     // Only the Five low bits are used for the cursor height.
        !          1424:     // Bit 5 is cursor enable, bit 6 and 7 preserved.
        !          1425:     //
        !          1426: 
        !          1427:     cursorLine = (UCHAR) CursorAttributes->Height & 0x1F;
        !          1428: 
        !          1429:     cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1430:         CRTC_DATA_PORT_COLOR) & 0xC0;
        !          1431: 
        !          1432:     if (!CursorAttributes->Enable) {
        !          1433: 
        !          1434:         cursorLine |= 0x20; // Flip cursor off bit
        !          1435: 
        !          1436:     }
        !          1437: 
        !          1438:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR,
        !          1439:                             cursorLine);
        !          1440: 
        !          1441:     //
        !          1442:     // Address Cursor End Register in CRT Controller Registers
        !          1443:     //
        !          1444: 
        !          1445:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1446:                                 CRTC_ADDRESS_PORT_COLOR,
        !          1447:                             IND_CURSOR_END);
        !          1448: 
        !          1449:     //
        !          1450:     // Set Cursor End Register. Preserve the high three bits of this
        !          1451:     // register.
        !          1452:     //
        !          1453: 
        !          1454:     cursorLine =
        !          1455:         (CursorAttributes->Width < (USHORT)(HwDeviceExtension->FontPelRows - 1)) ?
        !          1456:         CursorAttributes->Width : (HwDeviceExtension->FontPelRows - 1);
        !          1457: 
        !          1458:     cursorLine &= 0x1f;
        !          1459: 
        !          1460:     cursorLine |= VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1461:             CRTC_DATA_PORT_COLOR) & 0xE0;
        !          1462: 
        !          1463:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress + CRTC_DATA_PORT_COLOR,
        !          1464:                             cursorLine);
        !          1465: 
        !          1466:     return NO_ERROR;
        !          1467: 
        !          1468: } // end VgaSetCursorAttributes()
        !          1469: 
        !          1470: //---------------------------------------------------------------------------
        !          1471: BOOLEAN
        !          1472: VgaIsPresent(
        !          1473:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !          1474:     )
        !          1475: 
        !          1476: /*++
        !          1477: 
        !          1478: Routine Description:
        !          1479: 
        !          1480:     This routine returns TRUE if a VGA is present. Determining whether a VGA
        !          1481:     is present is a two-step process. First, this routine walks bits through
        !          1482:     the Bit Mask register, to establish that there are readable indexed
        !          1483:     registers (EGAs normally don't have readable registers, and other adapters
        !          1484:     are unlikely to have indexed registers). This test is done first because
        !          1485:     it's a non-destructive EGA rejection test (correctly rejects EGAs, but
        !          1486:     doesn't potentially mess up the screen or the accessibility of display
        !          1487:     memory). Normally, this would be an adequate test, but some EGAs have
        !          1488:     readable registers, so next, we check for the existence of the Chain4 bit
        !          1489:     in the Memory Mode register; this bit doesn't exist in EGAs. It's
        !          1490:     conceivable that there are EGAs with readable registers and a register bit
        !          1491:     where Chain4 is stored, although I don't know of any; if a better test yet
        !          1492:     is needed, memory could be written to in Chain4 mode, and then examined
        !          1493:     plane by plane in non-Chain4 mode to make sure the Chain4 bit did what it's
        !          1494:     supposed to do. However, the current test should be adequate to eliminate
        !          1495:     just about all EGAs, and 100% of everything else.
        !          1496: 
        !          1497:     If this function fails to find a VGA, it attempts to undo any damage it
        !          1498:     may have inadvertently done while testing. The underlying assumption for
        !          1499:     the damage control is that if there's any non-VGA adapter at the tested
        !          1500:     ports, it's an EGA or an enhanced EGA, because: a) I don't know of any
        !          1501:     other adapters that use 3C4/5 or 3CE/F, and b), if there are other
        !          1502:     adapters, I certainly don't know how to restore their original states. So
        !          1503:     all error recovery is oriented toward putting an EGA back in a writable
        !          1504:     state, so that error messages are visible. The EGA's state on entry is
        !          1505:     assumed to be text mode, so the Memory Mode register is restored to the
        !          1506:     default state for text mode.
        !          1507: 
        !          1508:     If a VGA is found, the VGA is returned to its original state after
        !          1509:     testing is finished.
        !          1510: 
        !          1511: Arguments:
        !          1512: 
        !          1513:     None.
        !          1514: 
        !          1515: Return Value:
        !          1516: 
        !          1517:     TRUE if a VGA is present, FALSE if not.
        !          1518: 
        !          1519: --*/
        !          1520: 
        !          1521: {
        !          1522:     UCHAR originalGCAddr;
        !          1523:     UCHAR originalSCAddr;
        !          1524:     UCHAR originalBitMask;
        !          1525:     UCHAR originalReadMap;
        !          1526:     UCHAR originalMemoryMode;
        !          1527:     UCHAR testMask;
        !          1528:     BOOLEAN returnStatus;
        !          1529: 
        !          1530:     //
        !          1531:     // Remember the original state of the Graphics Controller Address register.
        !          1532:     //
        !          1533: 
        !          1534:     originalGCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1535:             GRAPH_ADDRESS_PORT);
        !          1536: 
        !          1537:     //
        !          1538:     // Write the Read Map register with a known state so we can verify
        !          1539:     // that it isn't changed after we fool with the Bit Mask. This ensures
        !          1540:     // that we're dealing with indexed registers, since both the Read Map and
        !          1541:     // the Bit Mask are addressed at GRAPH_DATA_PORT.
        !          1542:     //
        !          1543: 
        !          1544:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1545:             GRAPH_ADDRESS_PORT, IND_READ_MAP);
        !          1546: 
        !          1547:     //
        !          1548:     // If we can't read back the Graphics Address register setting we just
        !          1549:     // performed, it's not readable and this isn't a VGA.
        !          1550:     //
        !          1551: 
        !          1552:     if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1553:         GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_READ_MAP) {
        !          1554: 
        !          1555:         return FALSE;
        !          1556:     }
        !          1557: 
        !          1558:     //
        !          1559:     // Set the Read Map register to a known state.
        !          1560:     //
        !          1561: 
        !          1562:     originalReadMap = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1563:             GRAPH_DATA_PORT);
        !          1564:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1565:             GRAPH_DATA_PORT, READ_MAP_TEST_SETTING);
        !          1566: 
        !          1567:     if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1568:             GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
        !          1569: 
        !          1570:         //
        !          1571:         // The Read Map setting we just performed can't be read back; not a
        !          1572:         // VGA. Restore the default Read Map state.
        !          1573:         //
        !          1574: 
        !          1575:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1576:                 GRAPH_DATA_PORT, READ_MAP_DEFAULT);
        !          1577: 
        !          1578:         return FALSE;
        !          1579:     }
        !          1580: 
        !          1581:     //
        !          1582:     // Remember the original setting of the Bit Mask register.
        !          1583:     //
        !          1584: 
        !          1585:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1586:             GRAPH_ADDRESS_PORT, IND_BIT_MASK);
        !          1587:     if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1588:                 GRAPH_ADDRESS_PORT) & GRAPH_ADDR_MASK) != IND_BIT_MASK) {
        !          1589: 
        !          1590:         //
        !          1591:         // The Graphics Address register setting we just made can't be read
        !          1592:         // back; not a VGA. Restore the default Read Map state.
        !          1593:         //
        !          1594: 
        !          1595:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1596:                 GRAPH_ADDRESS_PORT, IND_READ_MAP);
        !          1597:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1598:                 GRAPH_DATA_PORT, READ_MAP_DEFAULT);
        !          1599: 
        !          1600:         return FALSE;
        !          1601:     }
        !          1602: 
        !          1603:     originalBitMask = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1604:             GRAPH_DATA_PORT);
        !          1605: 
        !          1606:     //
        !          1607:     // Set up the initial test mask we'll write to and read from the Bit Mask.
        !          1608:     //
        !          1609: 
        !          1610:     testMask = 0xBB;
        !          1611: 
        !          1612:     do {
        !          1613: 
        !          1614:         //
        !          1615:         // Write the test mask to the Bit Mask.
        !          1616:         //
        !          1617: 
        !          1618:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1619:                 GRAPH_DATA_PORT, testMask);
        !          1620: 
        !          1621:         //
        !          1622:         // Make sure the Bit Mask remembered the value.
        !          1623:         //
        !          1624: 
        !          1625:         if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1626:                     GRAPH_DATA_PORT) != testMask) {
        !          1627: 
        !          1628:             //
        !          1629:             // The Bit Mask is not properly writable and readable; not a VGA.
        !          1630:             // Restore the Bit Mask and Read Map to their default states.
        !          1631:             //
        !          1632: 
        !          1633:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1634:                     GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
        !          1635:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1636:                     GRAPH_ADDRESS_PORT, IND_READ_MAP);
        !          1637:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1638:                     GRAPH_DATA_PORT, READ_MAP_DEFAULT);
        !          1639: 
        !          1640:             return FALSE;
        !          1641:         }
        !          1642: 
        !          1643:         //
        !          1644:         // Cycle the mask for next time.
        !          1645:         //
        !          1646: 
        !          1647:         testMask >>= 1;
        !          1648: 
        !          1649:     } while (testMask != 0);
        !          1650: 
        !          1651:     //
        !          1652:     // There's something readable at GRAPH_DATA_PORT; now switch back and
        !          1653:     // make sure that the Read Map register hasn't changed, to verify that
        !          1654:     // we're dealing with indexed registers.
        !          1655:     //
        !          1656: 
        !          1657:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1658:             GRAPH_ADDRESS_PORT, IND_READ_MAP);
        !          1659:     if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1660:                 GRAPH_DATA_PORT) != READ_MAP_TEST_SETTING) {
        !          1661: 
        !          1662:         //
        !          1663:         // The Read Map is not properly writable and readable; not a VGA.
        !          1664:         // Restore the Bit Mask and Read Map to their default states, in case
        !          1665:         // this is an EGA, so subsequent writes to the screen aren't garbled.
        !          1666:         //
        !          1667: 
        !          1668:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1669:                 GRAPH_DATA_PORT, READ_MAP_DEFAULT);
        !          1670:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1671:                 GRAPH_ADDRESS_PORT, IND_BIT_MASK);
        !          1672:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1673:                 GRAPH_DATA_PORT, BIT_MASK_DEFAULT);
        !          1674: 
        !          1675:         return FALSE;
        !          1676:     }
        !          1677: 
        !          1678:     //
        !          1679:     // We've pretty surely verified the existence of the Bit Mask register.
        !          1680:     // Put the Graphics Controller back to the original state.
        !          1681:     //
        !          1682: 
        !          1683:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1684:             GRAPH_DATA_PORT, originalReadMap);
        !          1685:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1686:             GRAPH_ADDRESS_PORT, IND_BIT_MASK);
        !          1687:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1688:             GRAPH_DATA_PORT, originalBitMask);
        !          1689:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1690:             GRAPH_ADDRESS_PORT, originalGCAddr);
        !          1691: 
        !          1692:     //
        !          1693:     // Now, check for the existence of the Chain4 bit.
        !          1694:     //
        !          1695: 
        !          1696:     //
        !          1697:     // Remember the original states of the Sequencer Address and Memory Mode
        !          1698:     // registers.
        !          1699:     //
        !          1700: 
        !          1701:     originalSCAddr = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1702:             SEQ_ADDRESS_PORT);
        !          1703:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1704:             SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
        !          1705:     if ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1706:             SEQ_ADDRESS_PORT) & SEQ_ADDR_MASK) != IND_MEMORY_MODE) {
        !          1707: 
        !          1708:         //
        !          1709:         // Couldn't read back the Sequencer Address register setting we just
        !          1710:         // performed.
        !          1711:         //
        !          1712: 
        !          1713:         return FALSE;
        !          1714:     }
        !          1715:     originalMemoryMode = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1716:             SEQ_DATA_PORT);
        !          1717: 
        !          1718:     //
        !          1719:     // Toggle the Chain4 bit and read back the result. This must be done during
        !          1720:     // sync reset, since we're changing the chaining state.
        !          1721:     //
        !          1722: 
        !          1723:     //
        !          1724:     // Begin sync reset.
        !          1725:     //
        !          1726: 
        !          1727:     VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          1728:              SEQ_ADDRESS_PORT),
        !          1729:              (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
        !          1730: 
        !          1731:     //
        !          1732:     // Toggle the Chain4 bit.
        !          1733:     //
        !          1734: 
        !          1735:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1736:             SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
        !          1737:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1738:             SEQ_DATA_PORT, (UCHAR)(originalMemoryMode ^ CHAIN4_MASK));
        !          1739: 
        !          1740:     if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1741:                 SEQ_DATA_PORT) != (UCHAR) (originalMemoryMode ^ CHAIN4_MASK)) {
        !          1742: 
        !          1743:         //
        !          1744:         // Chain4 bit not there; not a VGA.
        !          1745:         // Set text mode default for Memory Mode register.
        !          1746:         //
        !          1747: 
        !          1748:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1749:                 SEQ_DATA_PORT, MEMORY_MODE_TEXT_DEFAULT);
        !          1750:         //
        !          1751:         // End sync reset.
        !          1752:         //
        !          1753: 
        !          1754:         VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          1755:                 SEQ_ADDRESS_PORT),
        !          1756:                 (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
        !          1757: 
        !          1758:         returnStatus = FALSE;
        !          1759: 
        !          1760:     } else {
        !          1761: 
        !          1762:         //
        !          1763:         // It's a VGA.
        !          1764:         //
        !          1765: 
        !          1766:         //
        !          1767:         // Restore the original Memory Mode setting.
        !          1768:         //
        !          1769: 
        !          1770:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1771:                 SEQ_DATA_PORT, originalMemoryMode);
        !          1772: 
        !          1773:         //
        !          1774:         // End sync reset.
        !          1775:         //
        !          1776: 
        !          1777:         VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          1778:                 SEQ_ADDRESS_PORT),
        !          1779:                 (USHORT)(IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
        !          1780: 
        !          1781:         //
        !          1782:         // Restore the original Sequencer Address setting.
        !          1783:         //
        !          1784: 
        !          1785:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1786:                 SEQ_ADDRESS_PORT, originalSCAddr);
        !          1787: 
        !          1788:         returnStatus = TRUE;
        !          1789:     }
        !          1790: 
        !          1791:     return returnStatus;
        !          1792: 
        !          1793: } // VgaIsPresent()
        !          1794: 
        !          1795: //---------------------------------------------------------------------------
        !          1796: VP_STATUS
        !          1797: VgaSetPaletteReg(
        !          1798:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          1799:     PVIDEO_PALETTE_DATA PaletteBuffer,
        !          1800:     ULONG PaletteBufferSize
        !          1801:     )
        !          1802: 
        !          1803: /*++
        !          1804: 
        !          1805: Routine Description:
        !          1806: 
        !          1807:     This routine sets a specified portion of the EGA (not DAC) palette
        !          1808:     registers.
        !          1809: 
        !          1810: Arguments:
        !          1811: 
        !          1812:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          1813: 
        !          1814:     PaletteBuffer - Pointer to the structure containing the palette data.
        !          1815: 
        !          1816:     PaletteBufferSize - Length of the input buffer supplied by the user.
        !          1817: 
        !          1818: Return Value:
        !          1819: 
        !          1820:     NO_ERROR - information returned successfully
        !          1821: 
        !          1822:     ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
        !          1823: 
        !          1824:     ERROR_INVALID_PARAMETER - invalid palette size.
        !          1825: 
        !          1826: --*/
        !          1827: 
        !          1828: {
        !          1829:     USHORT i;
        !          1830: 
        !          1831:     //
        !          1832:     // Check if the size of the data in the input buffer is large enough.
        !          1833:     //
        !          1834: 
        !          1835:     if ((PaletteBufferSize) < (sizeof(VIDEO_PALETTE_DATA)) ||
        !          1836:         (PaletteBufferSize < (sizeof(VIDEO_PALETTE_DATA) +
        !          1837:                 (sizeof(USHORT) * (PaletteBuffer->NumEntries -1)) ))) {
        !          1838: 
        !          1839:         return ERROR_INSUFFICIENT_BUFFER;
        !          1840: 
        !          1841:     }
        !          1842: 
        !          1843:     //
        !          1844:     // Check to see if the parameters are valid.
        !          1845:     //
        !          1846: 
        !          1847:     if ( (PaletteBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER ) ||
        !          1848:          (PaletteBuffer->NumEntries == 0) ||
        !          1849:          (PaletteBuffer->FirstEntry + PaletteBuffer->NumEntries >
        !          1850:              VIDEO_MAX_PALETTE_REGISTER + 1 ) ) {
        !          1851: 
        !          1852:         return ERROR_INVALID_PARAMETER;
        !          1853: 
        !          1854:     }
        !          1855: 
        !          1856:     //
        !          1857:     // Reset ATC to index mode
        !          1858:     //
        !          1859: 
        !          1860:     VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          1861:                            ATT_INITIALIZE_PORT_COLOR);
        !          1862: 
        !          1863:     //
        !          1864:     // Blast out our palette values.
        !          1865:     //
        !          1866: 
        !          1867:     for (i = 0; i < PaletteBuffer->NumEntries; i++) {
        !          1868: 
        !          1869:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
        !          1870:                                 (UCHAR)(i+PaletteBuffer->FirstEntry));
        !          1871: 
        !          1872:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1873:                                     ATT_DATA_WRITE_PORT,
        !          1874:                                 (UCHAR)PaletteBuffer->Colors[i]);
        !          1875:     }
        !          1876: 
        !          1877:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT,
        !          1878:                             VIDEO_ENABLE);
        !          1879: 
        !          1880:     return NO_ERROR;
        !          1881: 
        !          1882: } // end VgaSetPaletteReg()
        !          1883: 
        !          1884: 
        !          1885: //---------------------------------------------------------------------------
        !          1886: VP_STATUS
        !          1887: VgaSetColorLookup(
        !          1888:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          1889:     PVIDEO_CLUT ClutBuffer,
        !          1890:     ULONG ClutBufferSize
        !          1891:     )
        !          1892: 
        !          1893: /*++
        !          1894: 
        !          1895: Routine Description:
        !          1896: 
        !          1897:     This routine sets a specified portion of the DAC color lookup table
        !          1898:     settings.
        !          1899: 
        !          1900: Arguments:
        !          1901: 
        !          1902:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          1903: 
        !          1904:     ClutBufferSize - Length of the input buffer supplied by the user.
        !          1905: 
        !          1906:     ClutBuffer - Pointer to the structure containing the color lookup table.
        !          1907: 
        !          1908: Return Value:
        !          1909: 
        !          1910:     NO_ERROR - information returned successfully
        !          1911: 
        !          1912:     ERROR_INSUFFICIENT_BUFFER - input buffer not large enough for input data.
        !          1913: 
        !          1914:     ERROR_INVALID_PARAMETER - invalid clut size.
        !          1915: 
        !          1916: --*/
        !          1917: 
        !          1918: {
        !          1919:     ULONG i;
        !          1920: 
        !          1921:     //
        !          1922:     // Check if the size of the data in the input buffer is large enough.
        !          1923:     //
        !          1924: 
        !          1925:     if ( (ClutBufferSize < sizeof(VIDEO_CLUT) - sizeof(ULONG)) ||
        !          1926:          (ClutBufferSize < sizeof(VIDEO_CLUT) +
        !          1927:                      (sizeof(ULONG) * (ClutBuffer->NumEntries - 1)) ) ) {
        !          1928: 
        !          1929:         return ERROR_INSUFFICIENT_BUFFER;
        !          1930: 
        !          1931:     }
        !          1932: 
        !          1933:     //
        !          1934:     // Check to see if the parameters are valid.
        !          1935:     //
        !          1936: 
        !          1937:     if ( (ClutBuffer->NumEntries == 0) ||
        !          1938:          (ClutBuffer->FirstEntry > VIDEO_MAX_COLOR_REGISTER) ||
        !          1939:          (ClutBuffer->FirstEntry + ClutBuffer->NumEntries >
        !          1940:              VIDEO_MAX_COLOR_REGISTER + 1) ) {
        !          1941: 
        !          1942:         return ERROR_INVALID_PARAMETER;
        !          1943: 
        !          1944:     }
        !          1945: 
        !          1946:     //
        !          1947:     //  Set CLUT registers directly on the hardware
        !          1948:     //
        !          1949: 
        !          1950:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          1951:                                 DAC_ADDRESS_WRITE_PORT,
        !          1952:                             (UCHAR) ClutBuffer->FirstEntry);
        !          1953: 
        !          1954:     for (i = 0; i < ClutBuffer->NumEntries; i++) {
        !          1955: 
        !          1956:         VideoPortWritePortBufferUchar((PUCHAR)HwDeviceExtension->IOAddress +
        !          1957:                                           DAC_DATA_REG_PORT,
        !          1958:                                       &(ClutBuffer->LookupTable[i].RgbArray.Red),
        !          1959:                                           0x03);
        !          1960: 
        !          1961:     }
        !          1962: 
        !          1963:     return NO_ERROR;
        !          1964: 
        !          1965: } // end VgaSetColorLookup()
        !          1966: 
        !          1967: //---------------------------------------------------------------------------
        !          1968: VP_STATUS
        !          1969: VgaRestoreHardwareState(
        !          1970:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          1971:     PVIDEO_HARDWARE_STATE HardwareState,
        !          1972:     ULONG HardwareStateSize
        !          1973:     )
        !          1974: 
        !          1975: /*++
        !          1976: 
        !          1977: Routine Description:
        !          1978: 
        !          1979:     Restores all registers and memory of the VGA.
        !          1980: 
        !          1981:     Note: HardwareState points to the actual buffer from which the state
        !          1982:     is to be restored. This buffer will always be big enough (we specified
        !          1983:     the required size at DriverEntry).
        !          1984: 
        !          1985:     Note: The offset in the hardware state header from which each general
        !          1986:     register is restored is the offset of the write address of that register
        !          1987:     from the base I/O address of the VGA.
        !          1988: 
        !          1989: 
        !          1990: Arguments:
        !          1991: 
        !          1992:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          1993: 
        !          1994:     HardwareState - Pointer to a structure from which the saved state is to be
        !          1995:         restored (actually only info about and a pointer to the actual save
        !          1996:         buffer).
        !          1997: 
        !          1998:     HardwareStateSize - Length of the input buffer supplied by the user.
        !          1999:         (Actually only the size of the HardwareState structure, not the
        !          2000:         buffer it points to from which the state is actually restored. The
        !          2001:         pointed-to buffer is assumed to be big enough.)
        !          2002: 
        !          2003: Return Value:
        !          2004: 
        !          2005:     NO_ERROR - restore performed successfully
        !          2006: 
        !          2007:     ERROR_INSUFFICIENT_BUFFER - input buffer not large enough to provide data
        !          2008: 
        !          2009: --*/
        !          2010: 
        !          2011: {
        !          2012:     PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
        !          2013:     ULONG i;
        !          2014:     UCHAR dummy;
        !          2015:     PUCHAR pScreen;
        !          2016:     PUCHAR pucLatch;
        !          2017:     PULONG pulBuffer;
        !          2018:     PUCHAR port;
        !          2019:     PUCHAR portValue;
        !          2020:     PUCHAR portValueDAC;
        !          2021:     ULONG bIsColor;
        !          2022: 
        !          2023: 
        !          2024:     //
        !          2025:     // Check if the size of the data in the input buffer is large enough.
        !          2026:     //
        !          2027: 
        !          2028:     if ((HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE)) ||
        !          2029:             (HardwareState->StateLength < VGA_TOTAL_STATE_SIZE)) {
        !          2030: 
        !          2031:             return ERROR_INSUFFICIENT_BUFFER;
        !          2032: 
        !          2033:     }
        !          2034: 
        !          2035:     //
        !          2036:     // Point to the buffer where the restore data is actually stored.
        !          2037:     //
        !          2038: 
        !          2039:     hardwareStateHeader = HardwareState->StateHeader;
        !          2040: 
        !          2041:     //
        !          2042:     // Make sure the offset are in the structure ...
        !          2043:     //
        !          2044: 
        !          2045:     if ((hardwareStateHeader->BasicSequencerOffset + VGA_NUM_SEQUENCER_PORTS >
        !          2046:             HardwareState->StateLength) ||
        !          2047: 
        !          2048:         (hardwareStateHeader->BasicCrtContOffset + VGA_NUM_CRTC_PORTS >
        !          2049:             HardwareState->StateLength) ||
        !          2050: 
        !          2051:         (hardwareStateHeader->BasicGraphContOffset + VGA_NUM_GRAPH_CONT_PORTS >
        !          2052:             HardwareState->StateLength) ||
        !          2053: 
        !          2054:         (hardwareStateHeader->BasicAttribContOffset + VGA_NUM_ATTRIB_CONT_PORTS >
        !          2055:             HardwareState->StateLength) ||
        !          2056: 
        !          2057:         (hardwareStateHeader->BasicDacOffset + (3 * VGA_NUM_DAC_ENTRIES) >
        !          2058:             HardwareState->StateLength) ||
        !          2059: 
        !          2060:         (hardwareStateHeader->BasicLatchesOffset + 4 >
        !          2061:             HardwareState->StateLength) ||
        !          2062: 
        !          2063:         (hardwareStateHeader->ExtendedSequencerOffset + EXT_NUM_SEQUENCER_PORTS >
        !          2064:             HardwareState->StateLength) ||
        !          2065: 
        !          2066:         (hardwareStateHeader->ExtendedCrtContOffset + EXT_NUM_CRTC_PORTS >
        !          2067:             HardwareState->StateLength) ||
        !          2068: 
        !          2069:         (hardwareStateHeader->ExtendedGraphContOffset + EXT_NUM_GRAPH_CONT_PORTS >
        !          2070:             HardwareState->StateLength) ||
        !          2071: 
        !          2072:         (hardwareStateHeader->ExtendedAttribContOffset + EXT_NUM_ATTRIB_CONT_PORTS >
        !          2073:             HardwareState->StateLength) ||
        !          2074: 
        !          2075:         (hardwareStateHeader->ExtendedDacOffset + (4 * EXT_NUM_DAC_ENTRIES) >
        !          2076:             HardwareState->StateLength) ||
        !          2077: 
        !          2078:         //
        !          2079:         // Only check the validator state offset if there is unemulated data.
        !          2080:         //
        !          2081: 
        !          2082:         ((hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) &&
        !          2083:             (hardwareStateHeader->ExtendedValidatorStateOffset + VGA_VALIDATOR_AREA_SIZE >
        !          2084:             HardwareState->StateLength)) ||
        !          2085: 
        !          2086:         (hardwareStateHeader->ExtendedMiscDataOffset + VGA_MISC_DATA_AREA_OFFSET >
        !          2087:             HardwareState->StateLength) ||
        !          2088: 
        !          2089:         (hardwareStateHeader->Plane1Offset + hardwareStateHeader->PlaneLength >
        !          2090:             HardwareState->StateLength) ||
        !          2091: 
        !          2092:         (hardwareStateHeader->Plane2Offset + hardwareStateHeader->PlaneLength >
        !          2093:             HardwareState->StateLength) ||
        !          2094: 
        !          2095:         (hardwareStateHeader->Plane3Offset + hardwareStateHeader->PlaneLength >
        !          2096:             HardwareState->StateLength) ||
        !          2097: 
        !          2098:         (hardwareStateHeader->Plane4Offset + hardwareStateHeader->PlaneLength >
        !          2099:             HardwareState->StateLength) ||
        !          2100: 
        !          2101:         (hardwareStateHeader->DIBOffset +
        !          2102:             hardwareStateHeader->DIBBitsPerPixel / 8 *
        !          2103:             hardwareStateHeader->DIBXResolution *
        !          2104:             hardwareStateHeader->DIBYResolution  > HardwareState->StateLength) ||
        !          2105: 
        !          2106:         (hardwareStateHeader->DIBXlatOffset + hardwareStateHeader->DIBXlatLength >
        !          2107:             HardwareState->StateLength)) {
        !          2108: 
        !          2109:         return ERROR_INVALID_PARAMETER;
        !          2110: 
        !          2111:     }
        !          2112: 
        !          2113:     //
        !          2114:     // Turn off the screen to avoid flickering. The screen will turn back on
        !          2115:     // when we restore the DAC state at the end of this routine.
        !          2116:     //
        !          2117: 
        !          2118:     if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          2119:             MISC_OUTPUT_REG_READ_PORT) & 0x01) {
        !          2120:         port = INPUT_STATUS_1_COLOR + HwDeviceExtension->IOAddress;
        !          2121:     } else {
        !          2122:         port = INPUT_STATUS_1_MONO + HwDeviceExtension->IOAddress;
        !          2123:     }
        !          2124: 
        !          2125:     //
        !          2126:     // Set DAC register 0 to display black.
        !          2127:     //
        !          2128: 
        !          2129:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2130:             DAC_ADDRESS_WRITE_PORT, 0);
        !          2131:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2132:             DAC_DATA_REG_PORT, 0);
        !          2133:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2134:             DAC_DATA_REG_PORT, 0);
        !          2135:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2136:             DAC_DATA_REG_PORT, 0);
        !          2137: 
        !          2138:     //
        !          2139:     // Set the DAC mask register to force DAC register 0 to display all the
        !          2140:     // time (this is the register we just set to display black). From now on,
        !          2141:     // nothing but black will show up on the screen.
        !          2142:     //
        !          2143: 
        !          2144:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2145:             DAC_PIXEL_MASK_PORT, 0);
        !          2146: 
        !          2147: 
        !          2148:     //
        !          2149:     // Restore the latches and the contents of display memory.
        !          2150:     //
        !          2151:     // Set up the VGA's hardware to allow us to copy to each plane in turn.
        !          2152:     //
        !          2153:     // Begin sync reset.
        !          2154:     //
        !          2155: 
        !          2156:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2157:             SEQ_ADDRESS_PORT),
        !          2158:             (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
        !          2159: 
        !          2160:     //
        !          2161:     // Turn off Chain mode and map display memory at A0000 for 64K.
        !          2162:     //
        !          2163: 
        !          2164:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2165:             GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
        !          2166:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2167:             GRAPH_DATA_PORT, (UCHAR) ((VideoPortReadPortUchar(
        !          2168:             HwDeviceExtension->IOAddress + GRAPH_DATA_PORT) & 0xF1) | 0x04));
        !          2169: 
        !          2170:     //
        !          2171:     // Turn off Chain4 mode and odd/even.
        !          2172:     //
        !          2173: 
        !          2174:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2175:             SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
        !          2176:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2177:             SEQ_DATA_PORT,
        !          2178:             (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          2179:             SEQ_DATA_PORT) & 0xF3) | 0x04));
        !          2180: 
        !          2181:     //
        !          2182:     // End sync reset.
        !          2183:     //
        !          2184: 
        !          2185:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2186:             SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
        !          2187:             (END_SYNC_RESET_VALUE << 8)));
        !          2188: 
        !          2189:     //
        !          2190:     // Set the write mode to 0, the read mode to 0, and turn off odd/even.
        !          2191:     //
        !          2192: 
        !          2193:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2194:             GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
        !          2195:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2196:             GRAPH_DATA_PORT,
        !          2197:             (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          2198:             GRAPH_DATA_PORT) & 0xE4) | 0x00));
        !          2199: 
        !          2200:     //
        !          2201:     // Set the Bit Mask to 0xFF to allow all CPU bits through.
        !          2202:     //
        !          2203: 
        !          2204:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2205:             GRAPH_ADDRESS_PORT), (USHORT) (IND_BIT_MASK + (0xFF << 8)));
        !          2206: 
        !          2207:     //
        !          2208:     // Set the Data Rotation and Logical Function fields to 0 to allow CPU
        !          2209:     // data through unmodified.
        !          2210:     //
        !          2211: 
        !          2212:     VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          2213:             GRAPH_ADDRESS_PORT), (USHORT) (IND_DATA_ROTATE + (0 << 8)));
        !          2214: 
        !          2215:     //
        !          2216:     // Set Set/Reset Enable to 0 to select CPU data for all planes.
        !          2217:     //
        !          2218: 
        !          2219:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2220:             GRAPH_ADDRESS_PORT), (USHORT) (IND_SET_RESET_ENABLE + (0 << 8)));
        !          2221: 
        !          2222:     //
        !          2223:     // Point the Sequencer Index to the Map Mask register.
        !          2224:     //
        !          2225: 
        !          2226:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2227:              SEQ_ADDRESS_PORT, IND_MAP_MASK);
        !          2228: 
        !          2229:     //
        !          2230:     // Restore the latches.
        !          2231:     //
        !          2232:     // Point to the saved data for the first latch.
        !          2233:     //
        !          2234: 
        !          2235:     pucLatch = ((PUCHAR) (hardwareStateHeader)) +
        !          2236:             hardwareStateHeader->BasicLatchesOffset;
        !          2237: 
        !          2238:     //
        !          2239:     // Point to first byte of display memory.
        !          2240:     //
        !          2241: 
        !          2242:     pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress;
        !          2243: 
        !          2244:     //
        !          2245:     // Write the contents to be restored to each of the four latches in turn.
        !          2246:     //
        !          2247: 
        !          2248:     for (i = 0; i < 4; i++) {
        !          2249: 
        !          2250:         //
        !          2251:         // Set the Map Mask to select the plane we want to restore next.
        !          2252:         //
        !          2253: 
        !          2254:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2255:                 SEQ_DATA_PORT, (UCHAR)(1<<i));
        !          2256: 
        !          2257:         //
        !          2258:         // Write this plane's latch.
        !          2259:         //
        !          2260: 
        !          2261:         VideoPortWriteRegisterUchar(pScreen, *pucLatch++);
        !          2262: 
        !          2263:     }
        !          2264: 
        !          2265:     //
        !          2266:     // Read the latched data into the latches, and the latches are set.
        !          2267:     //
        !          2268: 
        !          2269:     dummy = VideoPortReadRegisterUchar(pScreen);
        !          2270: 
        !          2271:     //
        !          2272:     // Point to the offset of the saved data for the first plane.
        !          2273:     //
        !          2274: 
        !          2275:     pulBuffer = &(hardwareStateHeader->Plane1Offset);
        !          2276: 
        !          2277:     //
        !          2278:     // Restore each of the four planes in turn.
        !          2279:     //
        !          2280: 
        !          2281:     for (i = 0; i < 4; i++) {
        !          2282: 
        !          2283:         //
        !          2284:         // Set the Map Mask to select the plane we want to restore next.
        !          2285:         //
        !          2286: 
        !          2287:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2288:                 SEQ_DATA_PORT, (UCHAR)(1<<i));
        !          2289: 
        !          2290:         //
        !          2291:         // Restore this plane from the buffer.
        !          2292:         //
        !          2293: 
        !          2294:         VideoPortMoveMemory((PUCHAR) HwDeviceExtension->VideoMemoryAddress,
        !          2295:                            ((PUCHAR) (hardwareStateHeader)) + *pulBuffer,
        !          2296:                            hardwareStateHeader->PlaneLength);
        !          2297: 
        !          2298:         pulBuffer++;
        !          2299: 
        !          2300:     }
        !          2301: 
        !          2302:     //
        !          2303:     // If we have some unemulated data, put it back into the buffer
        !          2304:     //
        !          2305: 
        !          2306:     if (hardwareStateHeader->VGAStateFlags & VIDEO_STATE_UNEMULATED_VGA_STATE) {
        !          2307: 
        !          2308:         if (!hardwareStateHeader->ExtendedValidatorStateOffset) {
        !          2309: 
        !          2310:             return ERROR_INVALID_PARAMETER;
        !          2311: 
        !          2312:         }
        !          2313: 
        !          2314:         //
        !          2315:         // Get the right offset in the struct and save all the data associated
        !          2316:         // with the trapped validator data.
        !          2317:         //
        !          2318: 
        !          2319:         VideoPortMoveMemory(&(HwDeviceExtension->TrappedValidatorCount),
        !          2320:                             ((PUCHAR) (hardwareStateHeader)) +
        !          2321:                                 hardwareStateHeader->ExtendedValidatorStateOffset,
        !          2322:                             VGA_VALIDATOR_AREA_SIZE);
        !          2323: 
        !          2324:         //
        !          2325:         // Check to see if this is an appropriate access range.
        !          2326:         // We are trapping - so we must have the trapping access range enabled.
        !          2327:         //
        !          2328: 
        !          2329:         if (((HwDeviceExtension->CurrentVdmAccessRange != FullVgaValidatorAccessRange) ||
        !          2330:              (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE)) &&
        !          2331:             ((HwDeviceExtension->CurrentVdmAccessRange != MinimalVgaValidatorAccessRange) ||
        !          2332:              (HwDeviceExtension->CurrentNumVdmAccessRanges != NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE))) {
        !          2333: 
        !          2334:             return ERROR_INVALID_PARAMETER;
        !          2335: 
        !          2336:         }
        !          2337: 
        !          2338:         VideoPortSetTrappedEmulatorPorts(HwDeviceExtension,
        !          2339:                                          HwDeviceExtension->CurrentNumVdmAccessRanges,
        !          2340:                                          HwDeviceExtension->CurrentVdmAccessRange);
        !          2341: 
        !          2342:     }
        !          2343: 
        !          2344:     //
        !          2345:     // Set the critical registers (clock and timing states) during sync reset.
        !          2346:     //
        !          2347:     // Begin sync reset.
        !          2348:     //
        !          2349: 
        !          2350:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2351:             SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
        !          2352:             (START_SYNC_RESET_VALUE << 8)));
        !          2353: 
        !          2354:     //
        !          2355:     // Restore the Miscellaneous Output register.
        !          2356:     //
        !          2357: 
        !          2358:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2359:             MISC_OUTPUT_REG_WRITE_PORT,
        !          2360:             (UCHAR) (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] & 0xF7));
        !          2361: 
        !          2362:     //
        !          2363:     // Restore all Sequencer registers except the Sync Reset register, which
        !          2364:     // is always not in reset (except when we send out a batched sync reset
        !          2365:     // register set, but that can't be interrupted, so we know we're never in
        !          2366:     // sync reset at save/restore time).
        !          2367:     //
        !          2368: 
        !          2369:     portValue = ((PUCHAR) hardwareStateHeader) +
        !          2370:             hardwareStateHeader->BasicSequencerOffset + 1;
        !          2371: 
        !          2372:     for (i = 1; i < VGA_NUM_SEQUENCER_PORTS; i++) {
        !          2373: 
        !          2374:         VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2375:                 SEQ_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)) );
        !          2376: 
        !          2377:     }
        !          2378: 
        !          2379:     //
        !          2380:     // Restore extended sequencer registers
        !          2381:     //
        !          2382: 
        !          2383: #ifdef EXTENDED_REGISTER_SAVE_RESTORE
        !          2384: 
        !          2385:     if (hardwareStateHeader->ExtendedSequencerOffset) {
        !          2386: 
        !          2387:         portValue = ((PUCHAR) hardwareStateHeader) +
        !          2388:                           hardwareStateHeader->ExtendedSequencerOffset;
        !          2389: 
        !          2390:         if (HwDeviceExtension->ChipType == CL542x) {
        !          2391: 
        !          2392:             //
        !          2393:             // No extended sequencer registers for the CL64xx
        !          2394:             //
        !          2395: 
        !          2396:             //
        !          2397:             // The first section in restore must open the extension registers
        !          2398:             //
        !          2399: 
        !          2400:             VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2401:                                          SEQ_ADDRESS_PORT),
        !          2402:                                      IND_CL_EXTS_ENB + (0x0012 << 8) );
        !          2403: 
        !          2404:             for (i = CL542x_SEQUENCER_EXT_START;
        !          2405:                  i <= CL542x_SEQUENCER_EXT_END;
        !          2406:                  i++) {
        !          2407: 
        !          2408:                 VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2409:                                              SEQ_ADDRESS_PORT),
        !          2410:                                          (USHORT) (i + ((*portValue++) << 8)) );
        !          2411: 
        !          2412:             }
        !          2413:         }
        !          2414:     }
        !          2415: 
        !          2416: #endif
        !          2417: 
        !          2418:     //
        !          2419:     // Restore the Graphics Controller Miscellaneous register, which contains
        !          2420:     // the Chain bit.
        !          2421:     //
        !          2422: 
        !          2423:     portValue = ((PUCHAR) hardwareStateHeader) +
        !          2424:                 hardwareStateHeader->BasicGraphContOffset + IND_GRAPH_MISC;
        !          2425: 
        !          2426:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2427:             GRAPH_ADDRESS_PORT), (USHORT)(IND_GRAPH_MISC + (*portValue << 8)));
        !          2428: 
        !          2429:     //
        !          2430:     // End sync reset.
        !          2431:     //
        !          2432: 
        !          2433:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2434:             SEQ_ADDRESS_PORT), (USHORT) (IND_SYNC_RESET +
        !          2435:             (END_SYNC_RESET_VALUE << 8)));
        !          2436: 
        !          2437:     //
        !          2438:     // Figure out if color/mono switchable registers are at 3BX or 3DX.
        !          2439:     // At the same time, save the state of the Miscellaneous Output register
        !          2440:     // which is read from 3CC but written at 3C2.
        !          2441:     //
        !          2442: 
        !          2443:     if (hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] & 0x01) {
        !          2444:         bIsColor = TRUE;
        !          2445:     } else {
        !          2446:         bIsColor = FALSE;
        !          2447:     }
        !          2448: 
        !          2449: 
        !          2450:     //
        !          2451:     // Restore the CRT Controller indexed registers.
        !          2452:     //
        !          2453:     // Unlock CRTC registers 0-7.
        !          2454:     //
        !          2455: 
        !          2456:     portValue = (PUCHAR) hardwareStateHeader +
        !          2457:             hardwareStateHeader->BasicCrtContOffset;
        !          2458: 
        !          2459:     if (bIsColor) {
        !          2460: 
        !          2461:         VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2462:                 CRTC_ADDRESS_PORT_COLOR), (USHORT) (IND_CRTC_PROTECT +
        !          2463:                 (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
        !          2464: 
        !          2465:     } else {
        !          2466: 
        !          2467:         VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2468:                 CRTC_ADDRESS_PORT_MONO), (USHORT) (IND_CRTC_PROTECT +
        !          2469:                 (((*(portValue + IND_CRTC_PROTECT)) & 0x7F) << 8)));
        !          2470: 
        !          2471:     }
        !          2472: 
        !          2473:     //
        !          2474:     // Restore extended crtc registers.
        !          2475:     //
        !          2476: 
        !          2477: #ifdef EXTENDED_REGISTER_SAVE_RESTORE
        !          2478: 
        !          2479:     if (hardwareStateHeader->ExtendedCrtContOffset) {
        !          2480: 
        !          2481:         portValue = (PUCHAR) hardwareStateHeader +
        !          2482:                          hardwareStateHeader->ExtendedCrtContOffset;
        !          2483: 
        !          2484:         if (HwDeviceExtension->ChipType == CL542x) {
        !          2485:  
        !          2486:             //
        !          2487:             // No CRTC Extensions in CL64xx chipset
        !          2488:             //
        !          2489: 
        !          2490:             for (i = CL542x_CRTC_EXT_START; i <= CL542x_CRTC_EXT_END; i++) {
        !          2491: 
        !          2492:                 if (bIsColor) {
        !          2493: 
        !          2494:                     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2495:                                                  CRTC_ADDRESS_PORT_COLOR),
        !          2496:                                              (USHORT) (i + ((*portValue++) << 8)));
        !          2497: 
        !          2498:                 } else {
        !          2499: 
        !          2500:                     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2501:                                                  CRTC_ADDRESS_PORT_MONO),
        !          2502:                                              (USHORT) (i + ((*portValue++) << 8)));
        !          2503: 
        !          2504:                 }
        !          2505:             }
        !          2506:         }
        !          2507:     }
        !          2508: 
        !          2509: #endif
        !          2510: 
        !          2511:     //
        !          2512:     // Now restore the CRTC registers.
        !          2513:     //
        !          2514: 
        !          2515:     portValue = (PUCHAR) hardwareStateHeader +
        !          2516:             hardwareStateHeader->BasicCrtContOffset;
        !          2517: 
        !          2518:     for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
        !          2519: 
        !          2520:         if (bIsColor) {
        !          2521: 
        !          2522:             VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2523:                     CRTC_ADDRESS_PORT_COLOR),
        !          2524:                     (USHORT) (i + ((*portValue++) << 8)));
        !          2525: 
        !          2526:         } else {
        !          2527: 
        !          2528:             VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2529:                     CRTC_ADDRESS_PORT_MONO),
        !          2530:                     (USHORT) (i + ((*portValue++) << 8)));
        !          2531: 
        !          2532:         }
        !          2533: 
        !          2534:     }
        !          2535: 
        !          2536:     //
        !          2537:     // Restore the Graphics Controller indexed registers.
        !          2538:     //
        !          2539: 
        !          2540:     portValue = (PUCHAR) hardwareStateHeader +
        !          2541:             hardwareStateHeader->BasicGraphContOffset;
        !          2542: 
        !          2543:     for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
        !          2544: 
        !          2545:         VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2546:                 GRAPH_ADDRESS_PORT), (USHORT) (i + ((*portValue++) << 8)));
        !          2547: 
        !          2548:     }
        !          2549: 
        !          2550:     //
        !          2551:     // Restore extended graphics controller registers.
        !          2552:     //
        !          2553: 
        !          2554: #ifdef EXTENDED_REGISTER_SAVE_RESTORE
        !          2555: 
        !          2556:     if (hardwareStateHeader->ExtendedGraphContOffset) {
        !          2557: 
        !          2558:     portValue = (PUCHAR) hardwareStateHeader +
        !          2559:                          hardwareStateHeader->ExtendedGraphContOffset;
        !          2560: 
        !          2561:         if (HwDeviceExtension->ChipType == CL542x) {
        !          2562: 
        !          2563:             for (i = CL542x_GRAPH_EXT_START; i <= CL542x_GRAPH_EXT_END; i++) {
        !          2564: 
        !          2565:                 VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2566:                                              GRAPH_ADDRESS_PORT),
        !          2567:                                          (USHORT) (i + ((*portValue++) << 8)));
        !          2568:             }
        !          2569: 
        !          2570:         } else {         // must be a CL64xx
        !          2571: 
        !          2572:             VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          2573:                                          GRAPH_ADDRESS_PORT),
        !          2574:                                      CL64xx_EXTENSION_ENABLE_INDEX +
        !          2575:                                          (CL64xx_EXTENSION_ENABLE_VALUE << 8));
        !          2576: 
        !          2577:             for (i = CL64xx_GRAPH_EXT_START; i <= CL64xx_GRAPH_EXT_END; i++) {
        !          2578: 
        !          2579:                 VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          2580:                                              GRAPH_ADDRESS_PORT),
        !          2581:                                          (USHORT) (i + ((*portValue++) << 8)));
        !          2582: 
        !          2583:             }
        !          2584:         }
        !          2585:     }
        !          2586: 
        !          2587: #endif 
        !          2588: 
        !          2589:     //
        !          2590:     // Restore the Attribute Controller indexed registers.
        !          2591:     //
        !          2592: 
        !          2593:     portValue = (PUCHAR) hardwareStateHeader +
        !          2594:             hardwareStateHeader->BasicAttribContOffset;
        !          2595: 
        !          2596:     //
        !          2597:     // Reset the AC index/data toggle, then blast out all the register
        !          2598:     // settings.
        !          2599:     //
        !          2600: 
        !          2601:     if (bIsColor) {
        !          2602:         dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          2603:                 INPUT_STATUS_1_COLOR);
        !          2604:     } else {
        !          2605:         dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          2606:                 INPUT_STATUS_1_MONO);
        !          2607:     }
        !          2608: 
        !          2609:     for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
        !          2610: 
        !          2611:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2612:                 ATT_ADDRESS_PORT, (UCHAR)i);
        !          2613:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2614:                 ATT_DATA_WRITE_PORT, *portValue++);
        !          2615: 
        !          2616:     }
        !          2617: 
        !          2618:     //
        !          2619:     // Restore DAC registers 1 through 255. We'll do register 0, the DAC Mask,
        !          2620:     // and the index registers later.
        !          2621:     // Set the DAC address port Index, then write out the DAC Data registers.
        !          2622:     // Each three reads get Red, Green, and Blue components for that register.
        !          2623:     //
        !          2624:     // Write them one at a time due to problems on local bus machines.
        !          2625:     //
        !          2626: 
        !          2627:     portValueDAC = (PUCHAR) hardwareStateHeader +
        !          2628:                    hardwareStateHeader->BasicDacOffset + 3;
        !          2629: 
        !          2630:     for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
        !          2631: 
        !          2632:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2633:                                 DAC_ADDRESS_WRITE_PORT, (UCHAR)i);
        !          2634: 
        !          2635:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2636:                                 DAC_DATA_REG_PORT, *portValueDAC++);
        !          2637: 
        !          2638:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2639:                                 DAC_DATA_REG_PORT, *portValueDAC++);
        !          2640: 
        !          2641:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2642:                                 DAC_DATA_REG_PORT, *portValueDAC++);
        !          2643: 
        !          2644:     }
        !          2645: 
        !          2646:     //
        !          2647:     // Is this color or mono ?
        !          2648:     //
        !          2649: 
        !          2650:     if (bIsColor) {
        !          2651:         port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
        !          2652:     } else {
        !          2653:         port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
        !          2654:     }
        !          2655: 
        !          2656:     //
        !          2657:     // Restore the Feature Control register.
        !          2658:     //
        !          2659: 
        !          2660:     if (bIsColor) {
        !          2661: 
        !          2662:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2663:                 FEAT_CTRL_WRITE_PORT_COLOR,
        !          2664:                 hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR]);
        !          2665: 
        !          2666:     } else {
        !          2667: 
        !          2668:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2669:                 FEAT_CTRL_WRITE_PORT_MONO,
        !          2670:                 hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO]);
        !          2671: 
        !          2672:     }
        !          2673: 
        !          2674: 
        !          2675:     //
        !          2676:     // Restore the Sequencer Index.
        !          2677:     //
        !          2678: 
        !          2679:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2680:             SEQ_ADDRESS_PORT,
        !          2681:             hardwareStateHeader->PortValue[SEQ_ADDRESS_PORT]);
        !          2682: 
        !          2683:     //
        !          2684:     // Restore the CRT Controller Index.
        !          2685:     //
        !          2686: 
        !          2687:     if (bIsColor) {
        !          2688: 
        !          2689:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2690:                 CRTC_ADDRESS_PORT_COLOR,
        !          2691:                 hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR]);
        !          2692: 
        !          2693:     } else {
        !          2694: 
        !          2695:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2696:                 CRTC_ADDRESS_PORT_MONO,
        !          2697:                 hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO]);
        !          2698: 
        !          2699:     }
        !          2700: 
        !          2701: 
        !          2702:     //
        !          2703:     // Restore the Graphics Controller Index.
        !          2704:     //
        !          2705: 
        !          2706:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2707:             GRAPH_ADDRESS_PORT,
        !          2708:             hardwareStateHeader->PortValue[GRAPH_ADDRESS_PORT]);
        !          2709: 
        !          2710: 
        !          2711:     //
        !          2712:     // Restore the Attribute Controller Index and index/data toggle state.
        !          2713:     //
        !          2714: 
        !          2715:     if (bIsColor) {
        !          2716:         port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
        !          2717:     } else {
        !          2718:         port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
        !          2719:     }
        !          2720: 
        !          2721:     VideoPortReadPortUchar(port);  // reset the toggle to Index state
        !          2722: 
        !          2723:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2724:             ATT_ADDRESS_PORT,  // restore the AC Index
        !          2725:             hardwareStateHeader->PortValue[ATT_ADDRESS_PORT]);
        !          2726: 
        !          2727:     //
        !          2728:     // If the toggle should be in Data state, we're all set. If it should be in
        !          2729:     // Index state, reset it to that condition.
        !          2730:     //
        !          2731: 
        !          2732:     if (hardwareStateHeader->AttribIndexDataState == 0) {
        !          2733: 
        !          2734:         //
        !          2735:         // Reset the toggle to Index state.
        !          2736:         //
        !          2737: 
        !          2738:         VideoPortReadPortUchar(port);
        !          2739: 
        !          2740:     }
        !          2741: 
        !          2742: 
        !          2743:     //
        !          2744:     // Restore DAC register 0 and the DAC Mask, to unblank the screen.
        !          2745:     //
        !          2746: 
        !          2747:     portValueDAC = (PUCHAR) hardwareStateHeader +
        !          2748:             hardwareStateHeader->BasicDacOffset;
        !          2749: 
        !          2750:     //
        !          2751:     // Restore the DAC Mask register.
        !          2752:     //
        !          2753: 
        !          2754:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2755:             DAC_PIXEL_MASK_PORT,
        !          2756:             hardwareStateHeader->PortValue[DAC_PIXEL_MASK_PORT]);
        !          2757: 
        !          2758:     //
        !          2759:     // Restore DAC register 0.
        !          2760:     //
        !          2761: 
        !          2762:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2763:             DAC_ADDRESS_WRITE_PORT, 0);
        !          2764:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2765:             DAC_DATA_REG_PORT, *portValueDAC++);
        !          2766:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2767:             DAC_DATA_REG_PORT, *portValueDAC++);
        !          2768:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2769:             DAC_DATA_REG_PORT, *portValueDAC++);
        !          2770: 
        !          2771: 
        !          2772:     //
        !          2773:     // Restore the read/write state and the current index of the DAC.
        !          2774:     //
        !          2775:     // See whether the Read or Write Index was written to most recently.
        !          2776:     // (The upper nibble stored at DAC_STATE_PORT is the # of reads/writes
        !          2777:     // for the current index.)
        !          2778:     //
        !          2779: 
        !          2780:     if ((hardwareStateHeader->PortValue[DAC_STATE_PORT] & 0x0F) == 3) {
        !          2781: 
        !          2782:         //
        !          2783:         // The DAC Read Index was written to last. Restore the DAC by setting
        !          2784:         // up to read from the saved index - 1, because the way the Read
        !          2785:         // Index works is that it autoincrements after reading, so you actually
        !          2786:         // end up reading the data for the index you read at the DAC Write
        !          2787:         // Mask register - 1.
        !          2788:         //
        !          2789:         // Set the Read Index to the index we read, minus 1, accounting for
        !          2790:         // wrap from 255 back to 0. The DAC hardware immediately reads this
        !          2791:         // register into a temporary buffer, then adds 1 to the index.
        !          2792:         //
        !          2793: 
        !          2794:         if (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] == 0) {
        !          2795: 
        !          2796:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2797:                     DAC_ADDRESS_READ_PORT, 255);
        !          2798: 
        !          2799:         } else {
        !          2800: 
        !          2801:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2802:                     DAC_ADDRESS_READ_PORT, (UCHAR)
        !          2803:                     (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] -
        !          2804:                     1));
        !          2805: 
        !          2806:         }
        !          2807: 
        !          2808:         //
        !          2809:         // Now read the hardware however many times are required to get to
        !          2810:         // the partial read state we saved.
        !          2811:         //
        !          2812: 
        !          2813:         for (i = hardwareStateHeader->PortValue[DAC_STATE_PORT] >> 4;
        !          2814:                 i > 0; i--) {
        !          2815: 
        !          2816:             dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          2817:                     DAC_DATA_REG_PORT);
        !          2818: 
        !          2819:         }
        !          2820: 
        !          2821:     } else {
        !          2822: 
        !          2823:         //
        !          2824:         // The DAC Write Index was written to last. Set the Write Index to the
        !          2825:         // index value we read out of the DAC. Then, if a partial write
        !          2826:         // (partway through an RGB triplet) was in place, write the partial
        !          2827:         // values, which we obtained by writing them to the current DAC
        !          2828:         // register. This DAC register will be wrong until the write is
        !          2829:         // completed, but at least the values will be right once the write is
        !          2830:         // finished, and most importantly we won't have messed up the sequence
        !          2831:         // of RGB writes (which can be as long as 768 in a row).
        !          2832:         //
        !          2833: 
        !          2834:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2835:                 DAC_ADDRESS_WRITE_PORT,
        !          2836:                 hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]);
        !          2837: 
        !          2838:         //
        !          2839:         // Now write to the hardware however many times are required to get to
        !          2840:         // the partial write state we saved (if any).
        !          2841:         //
        !          2842:         // Point to the saved value for the DAC register that was in the
        !          2843:         // process of being written to; we wrote the partial value out, so now
        !          2844:         // we can restore it.
        !          2845:         //
        !          2846: 
        !          2847:         portValueDAC = (PUCHAR) hardwareStateHeader +
        !          2848:                 hardwareStateHeader->BasicDacOffset +
        !          2849:                 (hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] * 3);
        !          2850: 
        !          2851:         for (i = hardwareStateHeader->PortValue[DAC_STATE_PORT] >> 4;
        !          2852:                 i > 0; i--) {
        !          2853: 
        !          2854:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          2855:                     DAC_DATA_REG_PORT, *portValueDAC++);
        !          2856: 
        !          2857:         }
        !          2858: 
        !          2859:     }
        !          2860: 
        !          2861:     return NO_ERROR;
        !          2862: 
        !          2863: } // end VgaRestoreHardwareState()
        !          2864: 
        !          2865: //---------------------------------------------------------------------------
        !          2866: VP_STATUS
        !          2867: VgaSaveHardwareState(
        !          2868:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          2869:     PVIDEO_HARDWARE_STATE HardwareState,
        !          2870:     ULONG HardwareStateSize,
        !          2871:     PULONG OutputSize
        !          2872:     )
        !          2873: 
        !          2874: /*++
        !          2875: 
        !          2876: Routine Description:
        !          2877: 
        !          2878:     Saves all registers and memory of the VGA.
        !          2879: 
        !          2880:     Note: HardwareState points to the actual buffer in which the state
        !          2881:     is saved. This buffer will always be big enough (we specified
        !          2882:     the required size at DriverEntry).
        !          2883: 
        !          2884:     Note: This routine leaves registers in any state it cares to, except
        !          2885:     that it will not mess with any of the CRT or Sequencer parameters that
        !          2886:     might make the monitor unhappy. It leaves the screen blanked by setting
        !          2887:     the DAC Mask and DAC register 0 to all zero values. The next video
        !          2888:     operation we expect after this is a mode set to take us back to Win32.
        !          2889: 
        !          2890:     Note: The offset in the hardware state header in which each general
        !          2891:     register is saved is the offset of the write address of that register from
        !          2892:     the base I/O address of the VGA.
        !          2893: 
        !          2894: Arguments:
        !          2895: 
        !          2896:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          2897: 
        !          2898:     HardwareState - Pointer to a structure in which the saved state will be
        !          2899:         returned (actually only info about and a pointer to the actual save
        !          2900:         buffer).
        !          2901: 
        !          2902:     HardwareStateSize - Length of the output buffer supplied by the user.
        !          2903:         (Actually only the size of the HardwareState structure, not the
        !          2904:         buffer it points to where the state is actually saved. The pointed-
        !          2905:         to buffer is assumed to be big enough.)
        !          2906: 
        !          2907:     OutputSize - Pointer to a buffer in which to return the actual size of
        !          2908:         the data returned in the buffer.
        !          2909: 
        !          2910: Return Value:
        !          2911: 
        !          2912:     NO_ERROR - information returned successfully
        !          2913: 
        !          2914:     ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
        !          2915:         any useful data
        !          2916: 
        !          2917: --*/
        !          2918: 
        !          2919: {
        !          2920:     PVIDEO_HARDWARE_STATE_HEADER hardwareStateHeader;
        !          2921:     PUCHAR port;
        !          2922:     PUCHAR pScreen;
        !          2923:     PUCHAR portValue;
        !          2924:     PUCHAR portValueDAC;
        !          2925:     PUCHAR bufferPointer;
        !          2926:     ULONG i;
        !          2927:     UCHAR dummy, originalACIndex, originalACData;
        !          2928:     UCHAR ucCRTC03;
        !          2929:     ULONG bIsColor;
        !          2930: 
        !          2931: 
        !          2932:     //
        !          2933:     // See if the buffer is big enough to hold the hardware state structure.
        !          2934:     // (This is only the HardwareState structure itself, not the buffer it
        !          2935:     // points to.)
        !          2936:     //
        !          2937: 
        !          2938:     if (HardwareStateSize < sizeof(VIDEO_HARDWARE_STATE) ) {
        !          2939: 
        !          2940:         *OutputSize = 0;  // nothing returned
        !          2941:         return ERROR_INSUFFICIENT_BUFFER;
        !          2942: 
        !          2943:     }
        !          2944: 
        !          2945:     //
        !          2946:     // Amount of data we're going to return in the output buffer.
        !          2947:     // (The VIDEO_HARDWARE_STATE in the output buffer points to the actual
        !          2948:     // buffer in which the state is stored, which is assumed to be large
        !          2949:     // enough.)
        !          2950:     //
        !          2951: 
        !          2952:     *OutputSize = sizeof(VIDEO_HARDWARE_STATE);
        !          2953: 
        !          2954:     //
        !          2955:     // Indicate the size of the full state save info.
        !          2956:     //
        !          2957: 
        !          2958:     HardwareState->StateLength = VGA_TOTAL_STATE_SIZE;
        !          2959: 
        !          2960:     //
        !          2961:     // hardwareStateHeader is a structure of offsets at the start of the
        !          2962:     // actual save area that indicates the locations in which various VGA
        !          2963:     // register and memory components are saved.
        !          2964:     //
        !          2965: 
        !          2966:     hardwareStateHeader = HardwareState->StateHeader;
        !          2967: 
        !          2968:     //
        !          2969:     // Zero out the structure.
        !          2970:     //
        !          2971: 
        !          2972:     VideoPortZeroMemory(hardwareStateHeader, sizeof(VIDEO_HARDWARE_STATE_HEADER));
        !          2973: 
        !          2974:     //
        !          2975:     // Set the Length field, which is basically a version ID.
        !          2976:     //
        !          2977: 
        !          2978:     hardwareStateHeader->Length = sizeof(VIDEO_HARDWARE_STATE_HEADER);
        !          2979: 
        !          2980:     //
        !          2981:     // Set the basic register offsets properly.
        !          2982:     //
        !          2983: 
        !          2984:     hardwareStateHeader->BasicSequencerOffset = VGA_BASIC_SEQUENCER_OFFSET;
        !          2985:     hardwareStateHeader->BasicCrtContOffset = VGA_BASIC_CRTC_OFFSET;
        !          2986:     hardwareStateHeader->BasicGraphContOffset = VGA_BASIC_GRAPH_CONT_OFFSET;
        !          2987:     hardwareStateHeader->BasicAttribContOffset = VGA_BASIC_ATTRIB_CONT_OFFSET;
        !          2988:     hardwareStateHeader->BasicDacOffset = VGA_BASIC_DAC_OFFSET;
        !          2989:     hardwareStateHeader->BasicLatchesOffset = VGA_BASIC_LATCHES_OFFSET;
        !          2990: 
        !          2991:     //
        !          2992:     // Set the entended register offsets properly.
        !          2993:     //
        !          2994: 
        !          2995:     hardwareStateHeader->ExtendedSequencerOffset = VGA_EXT_SEQUENCER_OFFSET;
        !          2996:     hardwareStateHeader->ExtendedCrtContOffset = VGA_EXT_CRTC_OFFSET;
        !          2997:     hardwareStateHeader->ExtendedGraphContOffset = VGA_EXT_GRAPH_CONT_OFFSET;
        !          2998:     hardwareStateHeader->ExtendedAttribContOffset = VGA_EXT_ATTRIB_CONT_OFFSET;
        !          2999:     hardwareStateHeader->ExtendedDacOffset = VGA_EXT_DAC_OFFSET;
        !          3000: 
        !          3001:     //
        !          3002:     // Figure out if color/mono switchable registers are at 3BX or 3DX.
        !          3003:     // At the same time, save the state of the Miscellaneous Output register
        !          3004:     // which is read from 3CC but written at 3C2.
        !          3005:     //
        !          3006: 
        !          3007:     if ((hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] =
        !          3008:             VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3009:                     MISC_OUTPUT_REG_READ_PORT))
        !          3010:             & 0x01) {
        !          3011:         bIsColor = TRUE;
        !          3012:     } else {
        !          3013:         bIsColor = FALSE;
        !          3014:     }
        !          3015: 
        !          3016:     //
        !          3017:     // Force the video subsystem enable state to enabled.
        !          3018:     //
        !          3019: 
        !          3020:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3021:             VIDEO_SUBSYSTEM_ENABLE_PORT, 1);
        !          3022: 
        !          3023:     //
        !          3024:     // Save the DAC state first, so we can set the DAC to blank the screen
        !          3025:     // so nothing after this shows up at all.
        !          3026:     //
        !          3027:     // Save the DAC Mask register.
        !          3028:     //
        !          3029: 
        !          3030:     hardwareStateHeader->PortValue[DAC_PIXEL_MASK_PORT] =
        !          3031:             VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3032:                     DAC_PIXEL_MASK_PORT);
        !          3033: 
        !          3034:     //
        !          3035:     // Save the DAC Index register. Note that there is actually only one DAC
        !          3036:     // Index register, which functions as either the Read Index or the Write
        !          3037:     // Index as needed.
        !          3038:     //
        !          3039: 
        !          3040:     hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT] =
        !          3041:             VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3042:                     DAC_ADDRESS_WRITE_PORT);
        !          3043: 
        !          3044:     //
        !          3045:     // Save the DAC read/write state. We determine if the DAC has been written
        !          3046:     // to or read from at the current index 0, 1, or 2 times (the application
        !          3047:     // is in the middle of reading or writing a DAC register triplet if the
        !          3048:     // count is 1 or 2), and save enough info so we can restore things
        !          3049:     // properly. The only hole is if the application writes to the Write Index,
        !          3050:     // then reads from instead of writes to the Data register, or vice-versa,
        !          3051:     // or if they do a partial read write, then never finish it.
        !          3052:     // This is fairly ridiculous behavior, however, and anyway there's nothing
        !          3053:     // we can do about it.
        !          3054:     //
        !          3055: 
        !          3056:     hardwareStateHeader->PortValue[DAC_STATE_PORT] =
        !          3057:              VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3058:                     DAC_STATE_PORT);
        !          3059: 
        !          3060:     if (hardwareStateHeader->PortValue[DAC_STATE_PORT] == 3) {
        !          3061: 
        !          3062:         //
        !          3063:         // The DAC Read Index was written to last. Figure out how many reads
        !          3064:         // have been done from the current index. We'll restart this on restore
        !          3065:         // by setting the Read Index to the current index - 1 (the read index
        !          3066:         // is one greater than the index being read), then doing the proper
        !          3067:         // number of reads.
        !          3068:         //
        !          3069:         // Read the Data register once, and see if the index changes.
        !          3070:         //
        !          3071: 
        !          3072:         dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3073:                 DAC_DATA_REG_PORT);
        !          3074: 
        !          3075:         if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3076:                     DAC_ADDRESS_WRITE_PORT) !=
        !          3077:                 hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
        !          3078: 
        !          3079:             //
        !          3080:             // The DAC Index changed, so two reads had already been done from
        !          3081:             // the current index. Store the count "2" in the upper nibble of
        !          3082:             // the read/write state field.
        !          3083:             //
        !          3084: 
        !          3085:             hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x20;
        !          3086: 
        !          3087:         } else {
        !          3088: 
        !          3089:             //
        !          3090:             // Read the Data register again, and see if the index changes.
        !          3091:             //
        !          3092: 
        !          3093:             dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3094:                     DAC_DATA_REG_PORT);
        !          3095: 
        !          3096:             if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3097:                         DAC_ADDRESS_WRITE_PORT) !=
        !          3098:                     hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
        !          3099: 
        !          3100:                 //
        !          3101:                 // The DAC Index changed, so one read had already been done
        !          3102:                 // from the current index. Store the count "1" in the upper
        !          3103:                 // nibble of the read/write state field.
        !          3104:                 //
        !          3105: 
        !          3106:                 hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x10;
        !          3107:             }
        !          3108: 
        !          3109:             //
        !          3110:             // If neither 2 nor 1 reads had been done from the current index,
        !          3111:             // then 0 reads were done, and we're all set, since the upper
        !          3112:             // nibble of the read/write state field is already 0.
        !          3113:             //
        !          3114: 
        !          3115:         }
        !          3116: 
        !          3117:     } else {
        !          3118: 
        !          3119:         //
        !          3120:         // The DAC Write Index was written to last. Figure out how many writes
        !          3121:         // have been done to the current index. We'll restart this on restore
        !          3122:         // by setting the Write Index to the proper index, then doing the
        !          3123:         // proper number of writes. When we do the DAC register save, we'll
        !          3124:         // read out the value that gets written (if there was a partial write
        !          3125:         // in progress), so we can restore the proper data later. This will
        !          3126:         // cause this current DAC location to be briefly wrong in the 1- and
        !          3127:         // 2-bytes-written case (until the app finishes the write), but that's
        !          3128:         // better than having the wrong DAC values written for good.
        !          3129:         //
        !          3130:         // Write the Data register once, and see if the index changes.
        !          3131:         //
        !          3132: 
        !          3133:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3134:                 DAC_DATA_REG_PORT, 0);
        !          3135: 
        !          3136:         if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3137:                     DAC_ADDRESS_WRITE_PORT) !=
        !          3138:                 hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
        !          3139: 
        !          3140:             //
        !          3141:             // The DAC Index changed, so two writes had already been done to
        !          3142:             // the current index. Store the count "2" in the upper nibble of
        !          3143:             // the read/write state field.
        !          3144:             //
        !          3145: 
        !          3146:             hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x20;
        !          3147: 
        !          3148:         } else {
        !          3149: 
        !          3150:             //
        !          3151:             // Write the Data register again, and see if the index changes.
        !          3152:             //
        !          3153: 
        !          3154:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3155:                     DAC_DATA_REG_PORT, 0);
        !          3156: 
        !          3157:             if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3158:                         DAC_ADDRESS_WRITE_PORT) !=
        !          3159:                     hardwareStateHeader->PortValue[DAC_ADDRESS_WRITE_PORT]) {
        !          3160: 
        !          3161:                 //
        !          3162:                 // The DAC Index changed, so one write had already been done
        !          3163:                 // to the current index. Store the count "1" in the upper
        !          3164:                 // nibble of the read/write state field.
        !          3165:                 //
        !          3166: 
        !          3167:                 hardwareStateHeader->PortValue[DAC_STATE_PORT] |= 0x10;
        !          3168:             }
        !          3169: 
        !          3170:             //
        !          3171:             // If neither 2 nor 1 writes had been done to the current index,
        !          3172:             // then 0 writes were done, and we're all set.
        !          3173:             //
        !          3174: 
        !          3175:         }
        !          3176: 
        !          3177:     }
        !          3178: 
        !          3179:     //
        !          3180:     // Now, read out the 256 18-bit DAC palette registers (256 RGB triplets),
        !          3181:     // and blank the screen.
        !          3182:     //
        !          3183: 
        !          3184:     portValueDAC = (PUCHAR) hardwareStateHeader + VGA_BASIC_DAC_OFFSET;
        !          3185: 
        !          3186:     //
        !          3187:     // Read out DAC register 0, so we can set it to black.
        !          3188:     //
        !          3189: 
        !          3190:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3191:                 DAC_ADDRESS_READ_PORT, 0);
        !          3192:     *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3193:             DAC_DATA_REG_PORT);
        !          3194:     *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3195:             DAC_DATA_REG_PORT);
        !          3196:     *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3197:             DAC_DATA_REG_PORT);
        !          3198: 
        !          3199:     //
        !          3200:     // Set DAC register 0 to display black.
        !          3201:     //
        !          3202: 
        !          3203:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3204:             DAC_ADDRESS_WRITE_PORT, 0);
        !          3205:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3206:             DAC_DATA_REG_PORT, 0);
        !          3207:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3208:             DAC_DATA_REG_PORT, 0);
        !          3209:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3210:             DAC_DATA_REG_PORT, 0);
        !          3211: 
        !          3212:     //
        !          3213:     // Set the DAC mask register to force DAC register 0 to display all the
        !          3214:     // time (this is the register we just set to display black). From now on,
        !          3215:     // nothing but black will show up on the screen.
        !          3216:     //
        !          3217: 
        !          3218:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3219:             DAC_PIXEL_MASK_PORT, 0);
        !          3220: 
        !          3221:     //
        !          3222:     // Read out the Attribute Controller Index state, and deduce the Index/Data
        !          3223:     // toggle state at the same time.
        !          3224:     //
        !          3225:     // Save the state of the Attribute Controller, both Index and Data,
        !          3226:     // so we can test in which state the toggle currently is.
        !          3227:     //
        !          3228: 
        !          3229:     originalACIndex = hardwareStateHeader->PortValue[ATT_ADDRESS_PORT] =
        !          3230:             VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3231:                     ATT_ADDRESS_PORT);
        !          3232:     originalACData = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3233:             ATT_DATA_READ_PORT);
        !          3234: 
        !          3235:     //
        !          3236:     // Sequencer Index.
        !          3237:     //
        !          3238: 
        !          3239:     hardwareStateHeader->PortValue[SEQ_ADDRESS_PORT] =
        !          3240:             VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3241:                     SEQ_ADDRESS_PORT);
        !          3242: 
        !          3243:     //
        !          3244:     // Begin sync reset, just in case this is an SVGA and the currently
        !          3245:     // indexed Attribute Controller register controls clocking stuff (a
        !          3246:     // normal VGA won't require this).
        !          3247:     //
        !          3248: 
        !          3249:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          3250:             SEQ_ADDRESS_PORT),
        !          3251:             (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
        !          3252: 
        !          3253:     //
        !          3254:     // Now, write a different Index setting to the Attribute Controller, and
        !          3255:     // see if the Index changes.
        !          3256:     //
        !          3257: 
        !          3258:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3259:             ATT_ADDRESS_PORT, (UCHAR) (originalACIndex ^ 0x10));
        !          3260: 
        !          3261:     if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3262:                 ATT_ADDRESS_PORT) == originalACIndex) {
        !          3263: 
        !          3264:         //
        !          3265:         // The Index didn't change, so the toggle was in the Data state.
        !          3266:         //
        !          3267: 
        !          3268:         hardwareStateHeader->AttribIndexDataState = 1;
        !          3269: 
        !          3270:         //
        !          3271:         // Restore the original Data state; we just corrupted it, and we need
        !          3272:         // to read it out later; also, it may glitch the screen if not
        !          3273:         // corrected. The toggle is already in the Index state.
        !          3274:         //
        !          3275: 
        !          3276:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3277:                 ATT_ADDRESS_PORT, originalACIndex);
        !          3278:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3279:                 ATT_DATA_WRITE_PORT, originalACData);
        !          3280: 
        !          3281:     } else {
        !          3282: 
        !          3283:         //
        !          3284:         // The Index did change, so the toggle was in the Index state.
        !          3285:         // No need to restore anything, because the Data register didn't
        !          3286:         // change, and we've already read out the Index register.
        !          3287:         //
        !          3288: 
        !          3289:         hardwareStateHeader->AttribIndexDataState = 0;
        !          3290: 
        !          3291:     }
        !          3292: 
        !          3293:     //
        !          3294:     // End sync reset.
        !          3295:     //
        !          3296: 
        !          3297:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          3298:             SEQ_ADDRESS_PORT),
        !          3299:             (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
        !          3300: 
        !          3301: 
        !          3302: 
        !          3303:     //
        !          3304:     // Save the rest of the DAC registers.
        !          3305:     // Set the DAC address port Index, then read out the DAC Data registers.
        !          3306:     // Each three reads get Red, Green, and Blue components for that register.
        !          3307:     //
        !          3308:     // Read them one at a time due to problems on local bus machines.
        !          3309:     //
        !          3310: 
        !          3311:     for (i = 1; i < VGA_NUM_DAC_ENTRIES; i++) {
        !          3312: 
        !          3313:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3314:                                 DAC_ADDRESS_READ_PORT, (UCHAR)i);
        !          3315: 
        !          3316:         *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3317:                                                  DAC_DATA_REG_PORT);
        !          3318: 
        !          3319:         *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3320:                                                  DAC_DATA_REG_PORT);
        !          3321: 
        !          3322:         *portValueDAC++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3323:                                                  DAC_DATA_REG_PORT);
        !          3324: 
        !          3325:     }
        !          3326: 
        !          3327:     //
        !          3328:     // Is this color or mono ?
        !          3329:     //
        !          3330: 
        !          3331:     if (bIsColor) {
        !          3332:         port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR;
        !          3333:     } else {
        !          3334:         port = HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO;
        !          3335:     }
        !          3336: 
        !          3337:     //
        !          3338:     // The Feature Control register is read from 3CA but written at 3BA/3DA.
        !          3339:     //
        !          3340: 
        !          3341:     if (bIsColor) {
        !          3342: 
        !          3343:         hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_COLOR] =
        !          3344:                 VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3345:                         FEAT_CTRL_READ_PORT);
        !          3346: 
        !          3347:     } else {
        !          3348: 
        !          3349:         hardwareStateHeader->PortValue[FEAT_CTRL_WRITE_PORT_MONO] =
        !          3350:                 VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3351:                         FEAT_CTRL_READ_PORT);
        !          3352: 
        !          3353:     }
        !          3354: 
        !          3355:     //
        !          3356:     // CRT Controller Index.
        !          3357:     //
        !          3358: 
        !          3359:     if (bIsColor) {
        !          3360: 
        !          3361:         hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_COLOR] =
        !          3362:                 VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3363:                         CRTC_ADDRESS_PORT_COLOR);
        !          3364: 
        !          3365:     } else {
        !          3366: 
        !          3367:         hardwareStateHeader->PortValue[CRTC_ADDRESS_PORT_MONO] =
        !          3368:                 VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3369:                         CRTC_ADDRESS_PORT_MONO);
        !          3370: 
        !          3371:     }
        !          3372: 
        !          3373:     //
        !          3374:     // Graphics Controller Index.
        !          3375:     //
        !          3376: 
        !          3377:     hardwareStateHeader->PortValue[GRAPH_ADDRESS_PORT] =
        !          3378:             VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3379:                     GRAPH_ADDRESS_PORT);
        !          3380: 
        !          3381: 
        !          3382:     //
        !          3383:     // Sequencer indexed registers.
        !          3384:     //
        !          3385: 
        !          3386:     portValue = ((PUCHAR) hardwareStateHeader) + VGA_BASIC_SEQUENCER_OFFSET;
        !          3387: 
        !          3388:     for (i = 0; i < VGA_NUM_SEQUENCER_PORTS; i++) {
        !          3389: 
        !          3390:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3391:                 SEQ_ADDRESS_PORT, (UCHAR)i);
        !          3392:         *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3393:                 SEQ_DATA_PORT);
        !          3394: 
        !          3395:     }
        !          3396: 
        !          3397:     //
        !          3398:     // Save extended sequencer registers.
        !          3399:     //
        !          3400: 
        !          3401: #ifdef EXTENDED_REGISTER_SAVE_RESTORE
        !          3402: 
        !          3403:     portValue = ((PUCHAR) hardwareStateHeader) + VGA_EXT_SEQUENCER_OFFSET;
        !          3404: 
        !          3405:     if (HwDeviceExtension->ChipType == CL542x) {
        !          3406: 
        !          3407:         //
        !          3408:         // No extended sequencer registers for the CL64xx         
        !          3409:         //
        !          3410: 
        !          3411:         for (i = CL542x_SEQUENCER_EXT_START;
        !          3412:              i <= CL542x_SEQUENCER_EXT_END;
        !          3413:              i++) {
        !          3414: 
        !          3415:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3416:                                     SEQ_ADDRESS_PORT, (UCHAR)i);
        !          3417: 
        !          3418:             *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3419:                                                   SEQ_DATA_PORT);
        !          3420: 
        !          3421:         }
        !          3422:     }
        !          3423: 
        !          3424: #endif
        !          3425: 
        !          3426:     //
        !          3427:     // CRT Controller indexed registers.
        !          3428:     //
        !          3429: 
        !          3430:     //
        !          3431:     // Remember the state of CRTC register 3, then force bit 7
        !          3432:     // to 1 so we will read back the Vertical Retrace start and
        !          3433:     // end registers rather than the light pen info.
        !          3434:     //
        !          3435: 
        !          3436:     if (bIsColor) {
        !          3437: 
        !          3438:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3439:                 CRTC_ADDRESS_PORT_COLOR, 3);
        !          3440:         ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3441:                         CRTC_DATA_PORT_COLOR);
        !          3442:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3443:                     CRTC_DATA_PORT_COLOR, (UCHAR) (ucCRTC03 | 0x80));
        !          3444:     } else {
        !          3445: 
        !          3446:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3447:                 CRTC_ADDRESS_PORT_MONO, 3);
        !          3448:         ucCRTC03 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3449:                         CRTC_DATA_PORT_MONO);
        !          3450:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3451:                 CRTC_DATA_PORT_MONO, (UCHAR) (ucCRTC03 | 0x80));
        !          3452:     }
        !          3453: 
        !          3454:     portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
        !          3455: 
        !          3456:     for (i = 0; i < VGA_NUM_CRTC_PORTS; i++) {
        !          3457: 
        !          3458:         if (bIsColor) {
        !          3459: 
        !          3460:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3461:                     CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
        !          3462:             *portValue++ =
        !          3463:                     VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3464:                             CRTC_DATA_PORT_COLOR);
        !          3465:             } 
        !          3466:         else {
        !          3467: 
        !          3468:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3469:                     CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
        !          3470:             *portValue++ =
        !          3471:                     VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3472:                             CRTC_DATA_PORT_MONO);
        !          3473:             }
        !          3474: 
        !          3475:        }
        !          3476: 
        !          3477:     portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_CRTC_OFFSET;
        !          3478:     portValue[3] = ucCRTC03;
        !          3479: 
        !          3480: 
        !          3481:     //
        !          3482:     // Save extended crtc registers.
        !          3483:     //
        !          3484: 
        !          3485: #ifdef EXTENDED_REGISTER_SAVE_RESTORE
        !          3486: 
        !          3487:     portValue = (PUCHAR) hardwareStateHeader + VGA_EXT_CRTC_OFFSET;
        !          3488: 
        !          3489:     if (HwDeviceExtension->ChipType == CL542x) {
        !          3490: 
        !          3491:         //
        !          3492:         // No CRTC Extensions in CL64xx chipset
        !          3493:         //
        !          3494: 
        !          3495:         for (i = CL542x_CRTC_EXT_START; i <= CL542x_CRTC_EXT_END; i++) {
        !          3496: 
        !          3497:             if (bIsColor) {
        !          3498: 
        !          3499:                 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3500:                                         CRTC_ADDRESS_PORT_COLOR, (UCHAR)i);
        !          3501: 
        !          3502:                 *portValue++ =
        !          3503:                     VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3504:                                            CRTC_DATA_PORT_COLOR);
        !          3505: 
        !          3506:             } else {
        !          3507: 
        !          3508:                 VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3509:                                         CRTC_ADDRESS_PORT_MONO, (UCHAR)i);
        !          3510: 
        !          3511:                 *portValue++ = 
        !          3512:                     VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3513:                                            CRTC_DATA_PORT_MONO);
        !          3514:             }
        !          3515:         }
        !          3516:     }
        !          3517: 
        !          3518: #endif
        !          3519: 
        !          3520:     //
        !          3521:     // Graphics Controller indexed registers.
        !          3522:     //
        !          3523: 
        !          3524:     portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_GRAPH_CONT_OFFSET;
        !          3525: 
        !          3526:     for (i = 0; i < VGA_NUM_GRAPH_CONT_PORTS; i++) {
        !          3527: 
        !          3528:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3529:                 GRAPH_ADDRESS_PORT, (UCHAR)i);
        !          3530:         *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3531:                 GRAPH_DATA_PORT);
        !          3532:          
        !          3533:         }
        !          3534: 
        !          3535:     //
        !          3536:     // Save extended graphics controller registers.
        !          3537:     //
        !          3538: 
        !          3539: #ifdef EXTENDED_REGISTER_SAVE_RESTORE
        !          3540: 
        !          3541:     portValue = (PUCHAR) hardwareStateHeader + VGA_EXT_GRAPH_CONT_OFFSET;
        !          3542: 
        !          3543:     if (HwDeviceExtension->ChipType == CL542x) {
        !          3544: 
        !          3545:         for (i = CL542x_GRAPH_EXT_START; i <= CL542x_GRAPH_EXT_END; i++) {
        !          3546: 
        !          3547:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3548:                                     GRAPH_ADDRESS_PORT, (UCHAR)i);
        !          3549: 
        !          3550:             *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3551:                                                   GRAPH_DATA_PORT);
        !          3552: 
        !          3553:         }
        !          3554: 
        !          3555:     } else {         // must be a CL64xx
        !          3556:        
        !          3557:         for (i = CL64xx_GRAPH_EXT_START; i <= CL64xx_GRAPH_EXT_END; i++) {
        !          3558: 
        !          3559:             VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3560:                                     GRAPH_ADDRESS_PORT, (UCHAR)i);
        !          3561: 
        !          3562:             *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3563:                                                   GRAPH_DATA_PORT);
        !          3564:         }
        !          3565:     }
        !          3566: 
        !          3567: #endif
        !          3568: 
        !          3569:     //
        !          3570:     // Attribute Controller indexed registers.
        !          3571:     //
        !          3572: 
        !          3573:     portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_ATTRIB_CONT_OFFSET;
        !          3574: 
        !          3575:     //
        !          3576:     // For each indexed AC register, reset the flip-flop for reading the
        !          3577:     // attribute register, then write the desired index to the AC Index,
        !          3578:     // then read the value of the indexed register from the AC Data register.
        !          3579:     //
        !          3580: 
        !          3581:     for (i = 0; i < VGA_NUM_ATTRIB_CONT_PORTS; i++) {
        !          3582: 
        !          3583:         if (bIsColor) {
        !          3584:             dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3585:                     INPUT_STATUS_1_COLOR);
        !          3586:         } else {
        !          3587:             dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3588:                     INPUT_STATUS_1_MONO);
        !          3589:         }
        !          3590: 
        !          3591:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3592:                 ATT_ADDRESS_PORT, (UCHAR)i);
        !          3593:         *portValue++ = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3594:                 ATT_DATA_READ_PORT);
        !          3595: 
        !          3596:     }
        !          3597: 
        !          3598:     //
        !          3599:     // Save the latches. This destroys one byte of display memory in each
        !          3600:     // plane, which is unfortunate but unavoidable. Chips that provide
        !          3601:     // a way to read back the latches can avoid this problem.
        !          3602:     //
        !          3603:     // Set up the VGA's hardware so we can write the latches, then read them
        !          3604:     // back.
        !          3605:     //
        !          3606: 
        !          3607:     //
        !          3608:     // Begin sync reset.
        !          3609:     //
        !          3610: 
        !          3611:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          3612:             SEQ_ADDRESS_PORT),
        !          3613:             (USHORT) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8)));
        !          3614: 
        !          3615:     //
        !          3616:     // Set the Miscellaneous register to make sure we can access video RAM.
        !          3617:     //
        !          3618: 
        !          3619:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3620:             MISC_OUTPUT_REG_WRITE_PORT, (UCHAR)(
        !          3621:             hardwareStateHeader->PortValue[MISC_OUTPUT_REG_WRITE_PORT] |
        !          3622:             0x02));
        !          3623: 
        !          3624:     //
        !          3625:     // Turn off Chain mode and map display memory at A0000 for 64K.
        !          3626:     //
        !          3627: 
        !          3628:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3629:             GRAPH_ADDRESS_PORT, IND_GRAPH_MISC);
        !          3630:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3631:             GRAPH_DATA_PORT,
        !          3632:             (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3633:             GRAPH_DATA_PORT) & 0xF1) | 0x04));
        !          3634: 
        !          3635:     //
        !          3636:     // Turn off Chain4 mode and odd/even.
        !          3637:     //
        !          3638: 
        !          3639:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3640:             SEQ_ADDRESS_PORT, IND_MEMORY_MODE);
        !          3641:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3642:             SEQ_DATA_PORT,
        !          3643:             (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3644:             SEQ_DATA_PORT) & 0xF3) | 0x04));
        !          3645: 
        !          3646:     //
        !          3647:     // End sync reset.
        !          3648:     //
        !          3649: 
        !          3650:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          3651:             SEQ_ADDRESS_PORT),
        !          3652:             (USHORT) (IND_SYNC_RESET + (END_SYNC_RESET_VALUE << 8)));
        !          3653: 
        !          3654:     //
        !          3655:     // Set the Map Mask to write to all planes.
        !          3656:     //
        !          3657: 
        !          3658:     VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          3659:             SEQ_ADDRESS_PORT), (USHORT) (IND_MAP_MASK + (0x0F << 8)));
        !          3660: 
        !          3661:     //
        !          3662:     // Set the write mode to 0, the read mode to 0, and turn off odd/even.
        !          3663:     //
        !          3664: 
        !          3665:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3666:             GRAPH_ADDRESS_PORT, IND_GRAPH_MODE);
        !          3667:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3668:             GRAPH_DATA_PORT,
        !          3669:             (UCHAR) ((VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          3670:             GRAPH_DATA_PORT) & 0xE4) | 0x01));
        !          3671: 
        !          3672:     //
        !          3673:     // Point to the last byte of display memory.
        !          3674:     //
        !          3675: 
        !          3676:     pScreen = (PUCHAR) HwDeviceExtension->VideoMemoryAddress +
        !          3677:             VGA_PLANE_SIZE - 1;
        !          3678: 
        !          3679:     //
        !          3680:     // Write the latches to the last byte of display memory.
        !          3681:     //
        !          3682: 
        !          3683:     VideoPortWriteRegisterUchar(pScreen, 0);
        !          3684: 
        !          3685:     //
        !          3686:     // Cycle through the four planes, reading the latch data from each plane.
        !          3687:     //
        !          3688: 
        !          3689:     //
        !          3690:     // Point the Graphics Controller Index to the Read Map register.
        !          3691:     //
        !          3692: 
        !          3693:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3694:             GRAPH_ADDRESS_PORT, IND_READ_MAP);
        !          3695: 
        !          3696:     portValue = (PUCHAR) hardwareStateHeader + VGA_BASIC_LATCHES_OFFSET;
        !          3697: 
        !          3698:     for (i=0; i<4; i++) {
        !          3699: 
        !          3700:         //
        !          3701:         // Set the Read Map for the current plane.
        !          3702:         //
        !          3703: 
        !          3704:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3705:                 GRAPH_DATA_PORT, (UCHAR)i);
        !          3706: 
        !          3707:         //
        !          3708:         // Read the latched data we've written to memory.
        !          3709:         //
        !          3710: 
        !          3711:         *portValue++ = VideoPortReadRegisterUchar(pScreen);
        !          3712: 
        !          3713:     }
        !          3714: 
        !          3715:     //
        !          3716:     // Set the VDM flags
        !          3717:     // We are a standard VGA, and then check if we have unemulated state.
        !          3718:     //
        !          3719: 
        !          3720:     hardwareStateHeader->VGAStateFlags = 0;
        !          3721: 
        !          3722: #ifdef EXTENDED_REGISTER_SAVE_RESTORE
        !          3723: 
        !          3724:     hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_NON_STANDARD_VGA;
        !          3725: 
        !          3726: #endif
        !          3727: 
        !          3728:     if (HwDeviceExtension->TrappedValidatorCount) {
        !          3729: 
        !          3730:         hardwareStateHeader->VGAStateFlags |= VIDEO_STATE_UNEMULATED_VGA_STATE;
        !          3731: 
        !          3732:         //
        !          3733:         // Save the VDM Emulator data
        !          3734:         // No need to save the state of the seuencer port register for our
        !          3735:         // emulated data since it may change when we come back. It will be
        !          3736:         // recomputed.
        !          3737:         //
        !          3738: 
        !          3739:         hardwareStateHeader->ExtendedValidatorStateOffset = VGA_VALIDATOR_OFFSET;
        !          3740: 
        !          3741:         VideoPortMoveMemory(((PUCHAR) (hardwareStateHeader)) +
        !          3742:                                 hardwareStateHeader->ExtendedValidatorStateOffset,
        !          3743:                             &(HwDeviceExtension->TrappedValidatorCount),
        !          3744:                             VGA_VALIDATOR_AREA_SIZE);
        !          3745: 
        !          3746:     } else {
        !          3747: 
        !          3748:         hardwareStateHeader->ExtendedValidatorStateOffset = 0;
        !          3749: 
        !          3750:     }
        !          3751: 
        !          3752:     //
        !          3753:     // Set the size of each plane.
        !          3754:     //
        !          3755: 
        !          3756:     hardwareStateHeader->PlaneLength = VGA_PLANE_SIZE;
        !          3757: 
        !          3758:     //
        !          3759:     // Store all the offsets for the planes in the structure.
        !          3760:     //
        !          3761: 
        !          3762:     hardwareStateHeader->Plane1Offset = VGA_PLANE_0_OFFSET;
        !          3763:     hardwareStateHeader->Plane2Offset = VGA_PLANE_1_OFFSET;
        !          3764:     hardwareStateHeader->Plane3Offset = VGA_PLANE_2_OFFSET;
        !          3765:     hardwareStateHeader->Plane4Offset = VGA_PLANE_3_OFFSET;
        !          3766: 
        !          3767:     //
        !          3768:     // Now copy the contents of video VRAM into the buffer.
        !          3769:     //
        !          3770:     // The VGA hardware is already set up so that video memory is readable;
        !          3771:     // we already turned off Chain mode, mapped in at A0000, turned off Chain4,
        !          3772:     // turned off odd/even, and set read mode 0 when we saved the latches.
        !          3773:     //
        !          3774:     // Point the Graphics Controller Index to the Read Map register.
        !          3775:     //
        !          3776: 
        !          3777:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3778:             GRAPH_ADDRESS_PORT, IND_READ_MAP);
        !          3779: 
        !          3780:     //
        !          3781:     // Point to the save area for the first plane.
        !          3782:     //
        !          3783: 
        !          3784:     bufferPointer = ((PUCHAR) (hardwareStateHeader)) +
        !          3785:                      hardwareStateHeader->Plane1Offset;
        !          3786: 
        !          3787:     //
        !          3788:     // Save the four planes consecutively.
        !          3789:     //
        !          3790: 
        !          3791:     for (i = 0; i < 4; i++) {
        !          3792: 
        !          3793:         //
        !          3794:         // Set the Read Map to select the plane we want to save next.
        !          3795:         //
        !          3796: 
        !          3797:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          3798:                 GRAPH_DATA_PORT, (UCHAR)i);
        !          3799: 
        !          3800:         //
        !          3801:         // Copy this plane into the buffer.
        !          3802:         //
        !          3803: 
        !          3804:         VideoPortMoveMemory(bufferPointer,
        !          3805:                            (PUCHAR) HwDeviceExtension->VideoMemoryAddress,
        !          3806:                            VGA_PLANE_SIZE);
        !          3807:         //
        !          3808:         // Point to the next plane's save area.
        !          3809:         //
        !          3810: 
        !          3811:         bufferPointer += VGA_PLANE_SIZE;
        !          3812:     }
        !          3813: 
        !          3814:     return NO_ERROR;
        !          3815: 
        !          3816: } // end VgaSaveHardwareState()
        !          3817: 
        !          3818: //---------------------------------------------------------------------------
        !          3819: VP_STATUS
        !          3820: VgaGetBankSelectCode(
        !          3821:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          3822:     PVIDEO_BANK_SELECT BankSelect,
        !          3823:     ULONG BankSelectSize,
        !          3824:     PULONG OutputSize
        !          3825:     )
        !          3826: 
        !          3827: /*++
        !          3828: 
        !          3829: Routine Description:
        !          3830: 
        !          3831:     Returns information needed in order for caller to implement bank
        !          3832:          management.
        !          3833: 
        !          3834: Arguments:
        !          3835: 
        !          3836:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          3837: 
        !          3838:     BankSelect - Pointer to a VIDEO_BANK_SELECT structure in which the bank
        !          3839:              select data will be returned (output buffer).
        !          3840: 
        !          3841:     BankSelectSize - Length of the output buffer supplied by the user.
        !          3842: 
        !          3843:     OutputSize - Pointer to a variable in which to return the actual size of
        !          3844:         the data returned in the output buffer.
        !          3845: 
        !          3846: Return Value:
        !          3847: 
        !          3848:     NO_ERROR - information returned successfully
        !          3849: 
        !          3850:     ERROR_MORE_DATA - output buffer not large enough to hold all info (but
        !          3851:         Size is returned, so caller can tell how large a buffer to allocate)
        !          3852: 
        !          3853:     ERROR_INSUFFICIENT_BUFFER - output buffer not large enough to return
        !          3854:         any useful data
        !          3855: 
        !          3856:     ERROR_INVALID_PARAMETER - invalid video mode selection
        !          3857: 
        !          3858: --*/
        !          3859: 
        !          3860: {
        !          3861: 
        !          3862:     ULONG codeSize;
        !          3863:     ULONG codePlanarSize;
        !          3864:     ULONG codeEnablePlanarSize;
        !          3865:     ULONG codeDisablePlanarSize;
        !          3866:     PUCHAR pCodeDest;
        !          3867:     PUCHAR pCodeBank;
        !          3868:     PUCHAR pCodePlanarBank;
        !          3869:     PUCHAR pCodeEnablePlanar;
        !          3870:     PUCHAR pCodeDisablePlanar;
        !          3871: 
        !          3872:     ULONG AdapterType = HwDeviceExtension->ChipType;
        !          3873:     PVIDEOMODE pMode = HwDeviceExtension->CurrentMode;
        !          3874: 
        !          3875:     //
        !          3876:     // The minimum passed buffer size is a VIDEO_BANK_SELECT
        !          3877:     // structure, so that we can return the required size; we can't do
        !          3878:     // anything if we don't have at least that much buffer.
        !          3879:     //
        !          3880: 
        !          3881:     if (BankSelectSize < sizeof(VIDEO_BANK_SELECT)) {
        !          3882: 
        !          3883:             return ERROR_INSUFFICIENT_BUFFER;
        !          3884: 
        !          3885:     }
        !          3886: 
        !          3887:     //
        !          3888:     // Determine the banking type, and set whether any banking is actually
        !          3889:     // supported in this mode.
        !          3890:     //
        !          3891: 
        !          3892:     BankSelect->BankingFlags = 0;
        !          3893:     codeSize = 0;
        !          3894:     codePlanarSize = 0;
        !          3895:     pCodeBank = NULL;
        !          3896: 
        !          3897:     switch(pMode->banktype) {
        !          3898: 
        !          3899:     case NoBanking:
        !          3900: 
        !          3901:         BankSelect->BankingType = VideoNotBanked;
        !          3902:         BankSelect->Granularity = 0;
        !          3903: 
        !          3904:         break;
        !          3905: 
        !          3906:     case PlanarHCBanking:
        !          3907: 
        !          3908:         BankSelect->BankingFlags = PLANAR_HC; // planar mode supported
        !          3909: 
        !          3910: #if ONE_64K_BANK
        !          3911:         //
        !          3912:         // The Cirrus Logic VGA's support one 64K read/write bank.
        !          3913:         //
        !          3914: 
        !          3915:         BankSelect->PlanarHCBankingType = VideoBanked1RW;
        !          3916:         BankSelect->PlanarHCGranularity = 0x10000; // 64K bank start adjustment
        !          3917:                                                    //  in planar HC mode as well
        !          3918: #endif
        !          3919: #if TWO_32K_BANKS
        !          3920:         //
        !          3921:         // The Cirrus Logic VGA's support two 32K read/write banks.
        !          3922:         //
        !          3923: 
        !          3924:         BankSelect->PlanarHCBankingType = VideoBanked2RW;
        !          3925:         BankSelect->PlanarHCGranularity = 0x8000; // 32K bank start adjustment
        !          3926:                                                   //  in planar HC mode as well
        !          3927: #endif
        !          3928: 
        !          3929:         // 64K bank start adjustment in planar HC mode as well
        !          3930: 
        !          3931:         if (HwDeviceExtension->ChipType == CL542x) {
        !          3932: 
        !          3933:             codePlanarSize =  ((ULONG)&CL542xPlanarHCBankSwitchEnd) -
        !          3934:                               ((ULONG)&CL542xPlanarHCBankSwitchStart);
        !          3935: 
        !          3936:             codeEnablePlanarSize = ((ULONG)&CL542xEnablePlanarHCEnd) -
        !          3937:                                    ((ULONG)&CL542xEnablePlanarHCStart);
        !          3938: 
        !          3939:             codeDisablePlanarSize = ((ULONG)&CL542xDisablePlanarHCEnd) -
        !          3940:                                     ((ULONG)&CL542xDisablePlanarHCStart);
        !          3941: 
        !          3942:             pCodePlanarBank = &CL542xPlanarHCBankSwitchStart;
        !          3943:             pCodeEnablePlanar = &CL542xEnablePlanarHCStart;
        !          3944:             pCodeDisablePlanar = &CL542xDisablePlanarHCStart;
        !          3945: 
        !          3946:         } else { // must be a CL64xx product
        !          3947: 
        !          3948:             codePlanarSize =  ((ULONG)&CL64xxPlanarHCBankSwitchEnd) -
        !          3949:                               ((ULONG)&CL64xxPlanarHCBankSwitchStart);
        !          3950: 
        !          3951:             codeEnablePlanarSize = ((ULONG)&CL64xxEnablePlanarHCEnd) -
        !          3952:                                    ((ULONG)&CL64xxEnablePlanarHCStart);
        !          3953: 
        !          3954:             codeDisablePlanarSize = ((ULONG)&CL64xxDisablePlanarHCEnd) -
        !          3955:                                     ((ULONG)&CL64xxDisablePlanarHCStart);
        !          3956: 
        !          3957:             pCodePlanarBank = &CL64xxPlanarHCBankSwitchStart;
        !          3958:             pCodeEnablePlanar = &CL64xxEnablePlanarHCStart;
        !          3959:             pCodeDisablePlanar = &CL64xxDisablePlanarHCStart;
        !          3960: 
        !          3961: 
        !          3962:         }
        !          3963: 
        !          3964:     //
        !          3965:     // Fall through to the normal banking case
        !          3966:     //
        !          3967: 
        !          3968:     case NormalBanking:
        !          3969: 
        !          3970: #if ONE_64K_BANK
        !          3971:         //
        !          3972:         // The Cirrus Logic VGA's support one 64K read/write bank.
        !          3973:         //
        !          3974: 
        !          3975:         BankSelect->BankingType = VideoBanked1RW;
        !          3976:         BankSelect->Granularity = 0x10000;
        !          3977: #endif
        !          3978: #if TWO_32K_BANKS
        !          3979:         //
        !          3980:         // The Cirrus Logic VGA's support two 32K read/write banks.
        !          3981:         //
        !          3982: 
        !          3983:         BankSelect->BankingType = VideoBanked2RW;
        !          3984:         BankSelect->Granularity = 0x8000;
        !          3985: #endif
        !          3986: 
        !          3987:         if (AdapterType == CL542x) {
        !          3988: 
        !          3989:             codeSize = ((ULONG)&CL542xBankSwitchEnd) -
        !          3990:                        ((ULONG)&CL542xBankSwitchStart);
        !          3991: 
        !          3992:             pCodeBank = &CL542xBankSwitchStart;
        !          3993: 
        !          3994:         } else { // must be a CL64xx
        !          3995: 
        !          3996:             codeSize = ((ULONG)&CL64xxBankSwitchEnd) -
        !          3997:                        ((ULONG)&CL64xxBankSwitchStart);
        !          3998: 
        !          3999:             pCodeBank = &CL64xxBankSwitchStart;
        !          4000: 
        !          4001:         }
        !          4002: 
        !          4003:         break;
        !          4004:     }
        !          4005: 
        !          4006:     //
        !          4007:     // Size of banking info.
        !          4008:     //
        !          4009: 
        !          4010:     BankSelect->Size = sizeof(VIDEO_BANK_SELECT) + codeSize;
        !          4011: 
        !          4012:     if (BankSelect->BankingFlags & PLANAR_HC) {
        !          4013: 
        !          4014:         BankSelect->Size += codePlanarSize + codeEnablePlanarSize +
        !          4015:             codeDisablePlanarSize;
        !          4016: 
        !          4017:     }
        !          4018: 
        !          4019:     //
        !          4020:     // This serves an a ID for the version of the structure we're using.
        !          4021:     //
        !          4022: 
        !          4023:     BankSelect->Length = sizeof(VIDEO_BANK_SELECT);
        !          4024: 
        !          4025:     //
        !          4026:     // If the buffer isn't big enough to hold all info, just return
        !          4027:     // ERROR_MORE_DATA; Size is already set.
        !          4028:     //
        !          4029: 
        !          4030:     if (BankSelectSize < BankSelect->Size ) {
        !          4031: 
        !          4032:         //
        !          4033:         // We're returning only the VIDEO_BANK_SELECT structure.
        !          4034:         //
        !          4035: 
        !          4036:         *OutputSize = sizeof(VIDEO_BANK_SELECT);
        !          4037:         return ERROR_MORE_DATA;
        !          4038:     }
        !          4039: 
        !          4040:     //
        !          4041:     // There's room enough for everything, so fill in all fields in
        !          4042:     // VIDEO_BANK_SELECT. (All fields are always returned; the caller can
        !          4043:     // just choose to ignore them, based on BankingFlags and BankingType.)
        !          4044:     //
        !          4045: 
        !          4046:     BankSelect->BitmapWidthInBytes = pMode->wbytes;
        !          4047:     BankSelect->BitmapSize = pMode->sbytes;
        !          4048: 
        !          4049:     //
        !          4050:     // Copy all banking code into the output buffer.
        !          4051:     //
        !          4052: 
        !          4053:     pCodeDest = (PUCHAR)BankSelect + sizeof(VIDEO_BANK_SELECT);
        !          4054: 
        !          4055:     if (pCodeBank != NULL) {
        !          4056: 
        !          4057:         BankSelect->CodeOffset = pCodeDest - (PUCHAR)BankSelect;
        !          4058: 
        !          4059:         VideoPortMoveMemory(pCodeDest,
        !          4060:                             pCodeBank,
        !          4061:                             codeSize);
        !          4062: 
        !          4063:         pCodeDest += codeSize;
        !          4064:     }
        !          4065: 
        !          4066:     if (BankSelect->BankingFlags & PLANAR_HC) {
        !          4067: 
        !          4068:         //
        !          4069:         // Copy appropriate high-color planar Bank Switch code:
        !          4070:         //
        !          4071: 
        !          4072:         BankSelect->PlanarHCBankCodeOffset = pCodeDest - (PUCHAR)BankSelect;
        !          4073: 
        !          4074:         VideoPortMoveMemory(pCodeDest,
        !          4075:                             pCodePlanarBank,
        !          4076:                             codePlanarSize);
        !          4077: 
        !          4078:         pCodeDest += codePlanarSize;
        !          4079: 
        !          4080:         //
        !          4081:         // Copy high-color planar bank mode Enable code:
        !          4082:         //
        !          4083: 
        !          4084:         BankSelect->PlanarHCEnableCodeOffset = pCodeDest - (PUCHAR)BankSelect;
        !          4085: 
        !          4086:         VideoPortMoveMemory(pCodeDest,
        !          4087:                             pCodeEnablePlanar,
        !          4088:                             codeEnablePlanarSize);
        !          4089: 
        !          4090:         pCodeDest += codeEnablePlanarSize;
        !          4091: 
        !          4092:         //
        !          4093:         // Copy high-color planar bank mode Disable code:
        !          4094:         //
        !          4095: 
        !          4096:         BankSelect->PlanarHCDisableCodeOffset = pCodeDest - (PUCHAR)BankSelect;
        !          4097: 
        !          4098:         VideoPortMoveMemory(pCodeDest,
        !          4099:                             pCodeDisablePlanar,
        !          4100:                             codeDisablePlanarSize);
        !          4101: 
        !          4102:     }
        !          4103: 
        !          4104:     //
        !          4105:     // Number of bytes we're returning is the full banking info size.
        !          4106:     //
        !          4107: 
        !          4108:     *OutputSize = BankSelect->Size;
        !          4109: 
        !          4110:     return NO_ERROR;
        !          4111: 
        !          4112: } // end VgaGetBankSelectCode()
        !          4113: 
        !          4114: //---------------------------------------------------------------------------
        !          4115: VP_STATUS
        !          4116: VgaValidatorUcharEntry(
        !          4117:     ULONG Context,
        !          4118:     ULONG Port,
        !          4119:     UCHAR AccessMode,
        !          4120:     PUCHAR Data
        !          4121:     )
        !          4122: 
        !          4123: /*++
        !          4124: 
        !          4125: Routine Description:
        !          4126: 
        !          4127:     Entry point into the validator for byte I/O operations.
        !          4128: 
        !          4129:     The entry point will be called whenever a byte operation was performed
        !          4130:     by a DOS application on one of the specified Video ports. The kernel
        !          4131:     emulator will forward these requests.
        !          4132: 
        !          4133: Arguments:
        !          4134: 
        !          4135:     Context - Context value that is passed to each call made to the validator
        !          4136:         function. This is the value the miniport driver specified in the
        !          4137:         MiniportConfigInfo->EmulatorAccessEntriesContext.
        !          4138: 
        !          4139:     Port - Port on which the operation is to be performed.
        !          4140: 
        !          4141:     AccessMode - Determines if it is a read or write operation.
        !          4142: 
        !          4143:     Data - Pointer to a variable containing the data to be written or a
        !          4144:         variable into which the read data should be stored.
        !          4145: 
        !          4146: Return Value:
        !          4147: 
        !          4148:     NO_ERROR.
        !          4149: 
        !          4150: --*/
        !          4151: 
        !          4152: {
        !          4153: 
        !          4154:     PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
        !          4155:     ULONG endEmulation;
        !          4156:     UCHAR temp;
        !          4157: 
        !          4158:     Port -= VGA_BASE_IO_PORT;
        !          4159: 
        !          4160:     if (hwDeviceExtension->TrappedValidatorCount) {
        !          4161: 
        !          4162:         //
        !          4163:         // If we are processing a WRITE instruction, then store it in the
        !          4164:         // playback buffer. If the buffer is full, then play it back right
        !          4165:         // away, end sync reset and reinitialize the buffer with a sync
        !          4166:         // reset instruction.
        !          4167:         //
        !          4168:         // If we have a READ, we must flush the buffer (which has the side
        !          4169:         // effect of starting SyncReset), perform the read operation, stop
        !          4170:         // sync reset, and put back a sync reset instruction in the buffer
        !          4171:         // so we can go on appropriately
        !          4172:         //
        !          4173: 
        !          4174:         if (AccessMode & EMULATOR_WRITE_ACCESS) {
        !          4175: 
        !          4176:             //
        !          4177:             // Make sure Bit 3 of the Miscellaneous register is always 0.
        !          4178:             // If it is 1 it could select a non-existent clock, and kill the
        !          4179:             // system
        !          4180:             //
        !          4181: 
        !          4182:             if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
        !          4183: 
        !          4184:                 *Data &= 0xF7;
        !          4185: 
        !          4186:             }
        !          4187: 
        !          4188:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4189:                 TrappedValidatorCount].Port = Port;
        !          4190: 
        !          4191:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4192:                 TrappedValidatorCount].AccessType = VGA_VALIDATOR_UCHAR_ACCESS;
        !          4193: 
        !          4194:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4195:                 TrappedValidatorCount].Data = *Data;
        !          4196: 
        !          4197:             hwDeviceExtension->TrappedValidatorCount++;
        !          4198: 
        !          4199:             //
        !          4200:             // Check to see if this instruction was ending sync reset.
        !          4201:             // If it did, we must flush the buffer and reset the trapped
        !          4202:             // IO ports to the minimal set.
        !          4203:             //
        !          4204: 
        !          4205:             if ( (Port == SEQ_DATA_PORT) &&
        !          4206:                  ((*Data & END_SYNC_RESET_VALUE) == END_SYNC_RESET_VALUE) &&
        !          4207:                  (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
        !          4208: 
        !          4209:                 endEmulation = 1;
        !          4210: 
        !          4211:             } else {
        !          4212: 
        !          4213:                 //
        !          4214:                 // If we are accessing the seq address port, keep track of the
        !          4215:                 // data value
        !          4216:                 //
        !          4217: 
        !          4218:                 if (Port == SEQ_ADDRESS_PORT) {
        !          4219: 
        !          4220:                     hwDeviceExtension->SequencerAddressValue = *Data;
        !          4221: 
        !          4222:                 }
        !          4223:     
        !          4224:                 //
        !          4225:                 // If the buffer is not full, then just return right away.
        !          4226:                 //
        !          4227: 
        !          4228:                 if (hwDeviceExtension->TrappedValidatorCount <
        !          4229:                        VGA_MAX_VALIDATOR_DATA - 1) {
        !          4230: 
        !          4231:                     return NO_ERROR;
        !          4232: 
        !          4233:                 }
        !          4234: 
        !          4235:                 endEmulation = 0;
        !          4236:             }
        !          4237:         }
        !          4238: 
        !          4239:         //
        !          4240:         // We are either in a READ path or a WRITE path that caused a
        !          4241:         // a full buffer. So flush the buffer either way.
        !          4242:         //
        !          4243:         // To do this put an END_SYNC_RESET at the end since we want to make
        !          4244:         // the buffer is ended sync reset ended.
        !          4245:         //
        !          4246: 
        !          4247:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4248:             TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
        !          4249: 
        !          4250:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4251:             TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
        !          4252: 
        !          4253:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4254:             TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
        !          4255:                                           (END_SYNC_RESET_VALUE << 8));
        !          4256: 
        !          4257:         hwDeviceExtension->TrappedValidatorCount++;
        !          4258: 
        !          4259:         VideoPortSynchronizeExecution(hwDeviceExtension,
        !          4260:                                       VpHighPriority,
        !          4261:                                       (PMINIPORT_SYNCHRONIZE_ROUTINE)
        !          4262:                                           VgaPlaybackValidatorData,
        !          4263:                                       hwDeviceExtension);
        !          4264: 
        !          4265:         //
        !          4266:         // Write back the real value of the sequencer address port.
        !          4267:         //
        !          4268: 
        !          4269:         VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
        !          4270:                                     SEQ_ADDRESS_PORT,
        !          4271:                                 (UCHAR) hwDeviceExtension->SequencerAddressValue);
        !          4272: 
        !          4273:         //
        !          4274:         // If we are in a READ path, read the data
        !          4275:         //
        !          4276: 
        !          4277:         if (AccessMode & EMULATOR_READ_ACCESS) {
        !          4278: 
        !          4279:             *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
        !          4280: 
        !          4281:             endEmulation = 0;
        !          4282: 
        !          4283:         }
        !          4284: 
        !          4285:         //
        !          4286:         // If we are ending emulation, reset trapping to the minimal amount
        !          4287:         // and exit.
        !          4288:         //
        !          4289: 
        !          4290:         if (endEmulation) {
        !          4291: 
        !          4292:             VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
        !          4293:                                              NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
        !          4294:                                              MinimalVgaValidatorAccessRange);
        !          4295: 
        !          4296:             return NO_ERROR;
        !          4297: 
        !          4298:         }
        !          4299: 
        !          4300:         //
        !          4301:         // For both cases, put back a START_SYNC_RESET in the buffer.
        !          4302:         //
        !          4303: 
        !          4304:         hwDeviceExtension->TrappedValidatorCount = 1;
        !          4305: 
        !          4306:         hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
        !          4307: 
        !          4308:         hwDeviceExtension->TrappedValidatorData[0].AccessType =
        !          4309:                 VGA_VALIDATOR_USHORT_ACCESS;
        !          4310: 
        !          4311:         hwDeviceExtension->TrappedValidatorData[0].Data =
        !          4312:                 (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
        !          4313: 
        !          4314:     } else {
        !          4315: 
        !          4316:         //
        !          4317:         // Nothing trapped.
        !          4318:         // Lets check is the IO is trying to do something that would require
        !          4319:         // us to stop trapping
        !          4320:         //
        !          4321: 
        !          4322:         if (AccessMode & EMULATOR_WRITE_ACCESS) {
        !          4323: 
        !          4324:             //
        !          4325:             // Make sure Bit 3 of the Miscelaneous register is always 0.
        !          4326:             // If it is 1 it could select a non-existant clock, and kill the
        !          4327:             // system
        !          4328:             //
        !          4329: 
        !          4330:             if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
        !          4331: 
        !          4332:                 temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
        !          4333:                                                   SEQ_ADDRESS_PORT);
        !          4334: 
        !          4335:                 VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
        !          4336:                                              SEQ_ADDRESS_PORT),
        !          4337:                                          (USHORT) (IND_SYNC_RESET +
        !          4338:                                              (START_SYNC_RESET_VALUE << 8)));
        !          4339: 
        !          4340:                 VideoPortWritePortUchar(hwDeviceExtension->IOAddress + Port,
        !          4341:                                          (UCHAR) (*Data & 0xF7) );
        !          4342: 
        !          4343:                 VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
        !          4344:                                              SEQ_ADDRESS_PORT),
        !          4345:                                          (USHORT) (IND_SYNC_RESET +
        !          4346:                                              (END_SYNC_RESET_VALUE << 8)));
        !          4347: 
        !          4348:                 VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
        !          4349:                                             SEQ_ADDRESS_PORT,
        !          4350:                                         temp);
        !          4351: 
        !          4352:                 return NO_ERROR;
        !          4353: 
        !          4354:             }
        !          4355: 
        !          4356:             //
        !          4357:             // If we get an access to the sequencer register, start trapping.
        !          4358:             //
        !          4359: 
        !          4360:             if ( (Port == SEQ_DATA_PORT) &&
        !          4361:                  ((*Data & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
        !          4362:                  (VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
        !          4363:                                          SEQ_ADDRESS_PORT) == IND_SYNC_RESET)) {
        !          4364: 
        !          4365:                 VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
        !          4366:                                                  NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
        !          4367:                                                  FullVgaValidatorAccessRange);
        !          4368: 
        !          4369:                 hwDeviceExtension->TrappedValidatorCount = 1;
        !          4370:                 hwDeviceExtension->TrappedValidatorData[0].Port = Port;
        !          4371:                 hwDeviceExtension->TrappedValidatorData[0].AccessType =
        !          4372:                     VGA_VALIDATOR_UCHAR_ACCESS;
        !          4373: 
        !          4374:                 hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
        !          4375: 
        !          4376:                 //
        !          4377:                 // Start keeping track of the state of the sequencer port.
        !          4378:                 //
        !          4379: 
        !          4380:                 hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
        !          4381: 
        !          4382:             } else {
        !          4383: 
        !          4384:                 VideoPortWritePortUchar(hwDeviceExtension->IOAddress + Port,
        !          4385:                                         *Data);
        !          4386: 
        !          4387:             }
        !          4388: 
        !          4389:         } else {
        !          4390: 
        !          4391:             *Data = VideoPortReadPortUchar(hwDeviceExtension->IOAddress + Port);
        !          4392: 
        !          4393:         }
        !          4394:     }
        !          4395: 
        !          4396:     return NO_ERROR;
        !          4397: 
        !          4398: } // end VgaValidatorUcharEntry()
        !          4399: 
        !          4400: //---------------------------------------------------------------------------
        !          4401: VP_STATUS
        !          4402: VgaValidatorUshortEntry(
        !          4403:     ULONG Context,
        !          4404:     ULONG Port,
        !          4405:     UCHAR AccessMode,
        !          4406:     PUSHORT Data
        !          4407:     )
        !          4408: 
        !          4409: /*++
        !          4410: 
        !          4411: Routine Description:
        !          4412: 
        !          4413:     Entry point into the validator for word I/O operations.
        !          4414: 
        !          4415:     The entry point will be called whenever a byte operation was performed
        !          4416:     by a DOS application on one of the specified Video ports. The kernel
        !          4417:     emulator will forward these requests.
        !          4418: 
        !          4419: Arguments:
        !          4420: 
        !          4421:     Context - Context value that is passed to each call made to the validator
        !          4422:         function. This is the value the miniport driver specified in the
        !          4423:         MiniportConfigInfo->EmulatorAccessEntriesContext.
        !          4424: 
        !          4425:     Port - Port on which the operation is to be performed.
        !          4426: 
        !          4427:     AccessMode - Determines if it is a read or write operation.
        !          4428: 
        !          4429:     Data - Pointer to a variable containing the data to be written or a
        !          4430:         variable into which the read data should be stored.
        !          4431: 
        !          4432: Return Value:
        !          4433: 
        !          4434:     NO_ERROR.
        !          4435: 
        !          4436: --*/
        !          4437: 
        !          4438: {
        !          4439: 
        !          4440:     PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
        !          4441:     ULONG endEmulation;
        !          4442:     UCHAR temp;
        !          4443: 
        !          4444:     Port -= VGA_BASE_IO_PORT;
        !          4445: 
        !          4446:     if (hwDeviceExtension->TrappedValidatorCount) {
        !          4447: 
        !          4448:         //
        !          4449:         // If we are processing a WRITE instruction, then store it in the
        !          4450:         // playback buffer. If the buffer is full, then play it back right
        !          4451:         // away, end sync reset and reinitialize the buffer with a sync
        !          4452:         // reset instruction.
        !          4453:         //
        !          4454:         // If we have a READ, we must flush the buffer (which has the side
        !          4455:         // effect of starting SyncReset), perform the read operation, stop
        !          4456:         // sync reset, and put back a sync reset instruction in the buffer
        !          4457:         // so we can go on appropriately
        !          4458:         //
        !          4459: 
        !          4460:         if (AccessMode & EMULATOR_WRITE_ACCESS) {
        !          4461: 
        !          4462:             //
        !          4463:             // Make sure Bit 3 of the Miscellaneous register is always 0.
        !          4464:             // If it is 1 it could select a non-existent clock, and kill the
        !          4465:             // system
        !          4466:             //
        !          4467: 
        !          4468:             if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
        !          4469: 
        !          4470:                 *Data &= 0xFFF7;
        !          4471: 
        !          4472:             }
        !          4473: 
        !          4474:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4475:                 TrappedValidatorCount].Port = Port;
        !          4476: 
        !          4477:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4478:                 TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
        !          4479: 
        !          4480:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4481:                 TrappedValidatorCount].Data = *Data;
        !          4482: 
        !          4483:             hwDeviceExtension->TrappedValidatorCount++;
        !          4484: 
        !          4485:             //
        !          4486:             // Check to see if this instruction was ending sync reset.
        !          4487:             // If it did, we must flush the buffer and reset the trapped
        !          4488:             // IO ports to the minimal set.
        !          4489:             //
        !          4490: 
        !          4491:             if (Port == SEQ_ADDRESS_PORT) {
        !          4492: 
        !          4493:                 //
        !          4494:                 // If we are accessing the seq address port, keep track of its
        !          4495:                 // value
        !          4496:                 //
        !          4497: 
        !          4498:                 hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
        !          4499: 
        !          4500:             }
        !          4501: 
        !          4502:             if ((Port == SEQ_ADDRESS_PORT) &&
        !          4503:                 ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
        !          4504:                    END_SYNC_RESET_VALUE) &&
        !          4505:                 (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
        !          4506: 
        !          4507:                 endEmulation = 1;
        !          4508: 
        !          4509:             } else {
        !          4510: 
        !          4511:                 //
        !          4512:                 // If the buffer is not full, then just return right away.
        !          4513:                 //
        !          4514: 
        !          4515:                 if (hwDeviceExtension->TrappedValidatorCount <
        !          4516:                        VGA_MAX_VALIDATOR_DATA - 1) {
        !          4517: 
        !          4518:                     return NO_ERROR;
        !          4519: 
        !          4520:                 }
        !          4521: 
        !          4522:                 endEmulation = 0;
        !          4523:             }
        !          4524:         }
        !          4525: 
        !          4526:         //
        !          4527:         // We are either in a READ path or a WRITE path that caused a
        !          4528:         // a full buffer. So flush the buffer either way.
        !          4529:         //
        !          4530:         // To do this put an END_SYNC_RESET at the end since we want to make
        !          4531:         // the buffer is ended sync reset ended.
        !          4532:         //
        !          4533: 
        !          4534:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4535:             TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
        !          4536: 
        !          4537:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4538:             TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
        !          4539: 
        !          4540:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4541:             TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
        !          4542:                                           (END_SYNC_RESET_VALUE << 8));
        !          4543: 
        !          4544:         hwDeviceExtension->TrappedValidatorCount++;
        !          4545: 
        !          4546:         VideoPortSynchronizeExecution(hwDeviceExtension,
        !          4547:                                       VpHighPriority,
        !          4548:                                       (PMINIPORT_SYNCHRONIZE_ROUTINE)
        !          4549:                                           VgaPlaybackValidatorData,
        !          4550:                                       hwDeviceExtension);
        !          4551: 
        !          4552:         //
        !          4553:         // Write back the real value of the sequencer address port.
        !          4554:         //
        !          4555: 
        !          4556:         VideoPortWritePortUchar((PUCHAR) (hwDeviceExtension->IOAddress +
        !          4557:                                     SEQ_ADDRESS_PORT),
        !          4558:                                 (UCHAR) hwDeviceExtension->SequencerAddressValue);
        !          4559: 
        !          4560:         //
        !          4561:         // If we are in a READ path, read the data
        !          4562:         //
        !          4563: 
        !          4564:         if (AccessMode & EMULATOR_READ_ACCESS) {
        !          4565: 
        !          4566:             *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress
        !          4567:                                                 + Port));
        !          4568: 
        !          4569:             endEmulation = 0;
        !          4570: 
        !          4571:         }
        !          4572: 
        !          4573:         //
        !          4574:         // If we are ending emulation, reset trapping to the minimal amount
        !          4575:         // and exit.
        !          4576:         //
        !          4577: 
        !          4578:         if (endEmulation) {
        !          4579: 
        !          4580:             VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
        !          4581:                                              NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
        !          4582:                                              MinimalVgaValidatorAccessRange);
        !          4583: 
        !          4584:             return NO_ERROR;
        !          4585: 
        !          4586:         }
        !          4587: 
        !          4588:         //
        !          4589:         // For both cases, put back a START_SYNC_RESET in the buffer.
        !          4590:         //
        !          4591: 
        !          4592:         hwDeviceExtension->TrappedValidatorCount = 1;
        !          4593: 
        !          4594:         hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
        !          4595: 
        !          4596:         hwDeviceExtension->TrappedValidatorData[0].AccessType =
        !          4597:                 VGA_VALIDATOR_USHORT_ACCESS;
        !          4598: 
        !          4599:         hwDeviceExtension->TrappedValidatorData[0].Data =
        !          4600:                 (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
        !          4601: 
        !          4602:     } else {
        !          4603: 
        !          4604:         //
        !          4605:         // Nothing trapped.
        !          4606:         // Lets check is the IO is trying to do something that would require
        !          4607:         // us to stop trapping
        !          4608:         //
        !          4609: 
        !          4610:         if (AccessMode & EMULATOR_WRITE_ACCESS) {
        !          4611: 
        !          4612:             //
        !          4613:             // Make sure Bit 3 of the Miscelaneous register is always 0.
        !          4614:             // If it is 1 it could select a non-existant clock, and kill the
        !          4615:             // system
        !          4616:             //
        !          4617: 
        !          4618:             if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
        !          4619: 
        !          4620:                 temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
        !          4621:                                                   SEQ_ADDRESS_PORT);
        !          4622: 
        !          4623:                 VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
        !          4624:                                              SEQ_ADDRESS_PORT),
        !          4625:                                          (USHORT) (IND_SYNC_RESET +
        !          4626:                                              (START_SYNC_RESET_VALUE << 8)));
        !          4627: 
        !          4628:                 VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
        !          4629:                                              (ULONG)Port),
        !          4630:                                          (USHORT) (*Data & 0xFFF7) );
        !          4631: 
        !          4632:                 VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
        !          4633:                                              SEQ_ADDRESS_PORT),
        !          4634:                                          (USHORT) (IND_SYNC_RESET +
        !          4635:                                              (END_SYNC_RESET_VALUE << 8)));
        !          4636: 
        !          4637:                 VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
        !          4638:                                         temp);
        !          4639: 
        !          4640:                 return NO_ERROR;
        !          4641: 
        !          4642:             }
        !          4643: 
        !          4644:             if ( (Port == SEQ_ADDRESS_PORT) &&
        !          4645:                  (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
        !          4646:                  ((*Data & 0xFF) == IND_SYNC_RESET)) {
        !          4647: 
        !          4648:                 VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
        !          4649:                                                  NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
        !          4650:                                                  FullVgaValidatorAccessRange);
        !          4651: 
        !          4652:                 hwDeviceExtension->TrappedValidatorCount = 1;
        !          4653:                 hwDeviceExtension->TrappedValidatorData[0].Port = Port;
        !          4654:                 hwDeviceExtension->TrappedValidatorData[0].AccessType =
        !          4655:                     VGA_VALIDATOR_USHORT_ACCESS;
        !          4656: 
        !          4657:                 hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
        !          4658: 
        !          4659:                 //
        !          4660:                 // Start keeping track of the state of the sequencer port.
        !          4661:                 //
        !          4662: 
        !          4663:                 hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
        !          4664: 
        !          4665:             } else {
        !          4666: 
        !          4667:                 VideoPortWritePortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
        !          4668:                                              Port),
        !          4669:                                          *Data);
        !          4670: 
        !          4671:             }
        !          4672: 
        !          4673:         } else {
        !          4674: 
        !          4675:             *Data = VideoPortReadPortUshort((PUSHORT)(hwDeviceExtension->IOAddress +
        !          4676:                                             Port));
        !          4677: 
        !          4678:         }
        !          4679:     }
        !          4680: 
        !          4681:     return NO_ERROR;
        !          4682: 
        !          4683: } // end VgaValidatorUshortEntry()
        !          4684: 
        !          4685: //---------------------------------------------------------------------------
        !          4686: VP_STATUS
        !          4687: VgaValidatorUlongEntry(
        !          4688:     ULONG Context,
        !          4689:     ULONG Port,
        !          4690:     UCHAR AccessMode,
        !          4691:     PULONG Data
        !          4692:     )
        !          4693: 
        !          4694: /*++
        !          4695: 
        !          4696: Routine Description:
        !          4697: 
        !          4698:     Entry point into the validator for dword I/O operations.
        !          4699: 
        !          4700:     The entry point will be called whenever a byte operation was performed
        !          4701:     by a DOS application on one of the specified Video ports. The kernel
        !          4702:     emulator will forward these requests.
        !          4703: 
        !          4704: Arguments:
        !          4705: 
        !          4706:     Context - Context value that is passed to each call made to the validator
        !          4707:         function. This is the value the miniport driver specified in the
        !          4708:         MiniportConfigInfo->EmulatorAccessEntriesContext.
        !          4709: 
        !          4710:     Port - Port on which the operation is to be performed.
        !          4711: 
        !          4712:     AccessMode - Determines if it is a read or write operation.
        !          4713: 
        !          4714:     Data - Pointer to a variable containing the data to be written or a
        !          4715:         variable into which the read data should be stored.
        !          4716: 
        !          4717: Return Value:
        !          4718: 
        !          4719:     NO_ERROR.
        !          4720: 
        !          4721: --*/
        !          4722: 
        !          4723: {
        !          4724: 
        !          4725:     PHW_DEVICE_EXTENSION hwDeviceExtension = (PHW_DEVICE_EXTENSION) Context;
        !          4726:     ULONG endEmulation;
        !          4727:     UCHAR temp;
        !          4728: 
        !          4729:     Port -= VGA_BASE_IO_PORT;
        !          4730: 
        !          4731:     if (hwDeviceExtension->TrappedValidatorCount) {
        !          4732: 
        !          4733:         //
        !          4734:         // If we are processing a WRITE instruction, then store it in the
        !          4735:         // playback buffer. If the buffer is full, then play it back right
        !          4736:         // away, end sync reset and reinitialize the buffer with a sync
        !          4737:         // reset instruction.
        !          4738:         //
        !          4739:         // If we have a READ, we must flush the buffer (which has the side
        !          4740:         // effect of starting SyncReset), perform the read operation, stop
        !          4741:         // sync reset, and put back a sync reset instruction in the buffer
        !          4742:         // so we can go on appropriately
        !          4743:         //
        !          4744: 
        !          4745:         if (AccessMode & EMULATOR_WRITE_ACCESS) {
        !          4746: 
        !          4747:             //
        !          4748:             // Make sure Bit 3 of the Miscellaneous register is always 0.
        !          4749:             // If it is 1 it could select a non-existent clock, and kill the
        !          4750:             // system
        !          4751:             //
        !          4752: 
        !          4753:             if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
        !          4754: 
        !          4755:                 *Data &= 0xFFFFFFF7;
        !          4756: 
        !          4757:             }
        !          4758: 
        !          4759:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4760:                 TrappedValidatorCount].Port = Port;
        !          4761: 
        !          4762:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4763:                 TrappedValidatorCount].AccessType = VGA_VALIDATOR_ULONG_ACCESS;
        !          4764: 
        !          4765:             hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4766:                 TrappedValidatorCount].Data = *Data;
        !          4767: 
        !          4768:             hwDeviceExtension->TrappedValidatorCount++;
        !          4769: 
        !          4770:             //
        !          4771:             // Check to see if this instruction was ending sync reset.
        !          4772:             // If it did, we must flush the buffer and reset the trapped
        !          4773:             // IO ports to the minimal set.
        !          4774:             //
        !          4775: 
        !          4776:             if (Port == SEQ_ADDRESS_PORT) {
        !          4777: 
        !          4778:                 //
        !          4779:                 // If we are accessing the seq address port, keep track of its
        !          4780:                 // value
        !          4781:                 //
        !          4782: 
        !          4783:                 hwDeviceExtension->SequencerAddressValue = (*Data & 0xFF);
        !          4784: 
        !          4785:             }
        !          4786: 
        !          4787:             if ((Port == SEQ_ADDRESS_PORT) &&
        !          4788:                 ( ((*Data >> 8) & END_SYNC_RESET_VALUE) ==
        !          4789:                    END_SYNC_RESET_VALUE) &&
        !          4790:                 (hwDeviceExtension->SequencerAddressValue == IND_SYNC_RESET)) {
        !          4791: 
        !          4792:                 endEmulation = 1;
        !          4793: 
        !          4794:             } else {
        !          4795: 
        !          4796:                 //
        !          4797:                 // If the buffer is not full, then just return right away.
        !          4798:                 //
        !          4799: 
        !          4800:                 if (hwDeviceExtension->TrappedValidatorCount <
        !          4801:                        VGA_MAX_VALIDATOR_DATA - 1) {
        !          4802: 
        !          4803:                     return NO_ERROR;
        !          4804: 
        !          4805:                 }
        !          4806: 
        !          4807:                 endEmulation = 0;
        !          4808:             }
        !          4809:         }
        !          4810: 
        !          4811:         //
        !          4812:         // We are either in a READ path or a WRITE path that caused a
        !          4813:         // a full buffer. So flush the buffer either way.
        !          4814:         //
        !          4815:         // To do this put an END_SYNC_RESET at the end since we want to make
        !          4816:         // the buffer is ended sync reset ended.
        !          4817:         //
        !          4818: 
        !          4819:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4820:             TrappedValidatorCount].Port = SEQ_ADDRESS_PORT;
        !          4821: 
        !          4822:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4823:             TrappedValidatorCount].AccessType = VGA_VALIDATOR_USHORT_ACCESS;
        !          4824: 
        !          4825:         hwDeviceExtension->TrappedValidatorData[hwDeviceExtension->
        !          4826:             TrappedValidatorCount].Data = (USHORT) (IND_SYNC_RESET +
        !          4827:                                           (END_SYNC_RESET_VALUE << 8));
        !          4828: 
        !          4829:         hwDeviceExtension->TrappedValidatorCount++;
        !          4830: 
        !          4831:         VideoPortSynchronizeExecution(hwDeviceExtension,
        !          4832:                                       VpHighPriority,
        !          4833:                                       (PMINIPORT_SYNCHRONIZE_ROUTINE)
        !          4834:                                           VgaPlaybackValidatorData,
        !          4835:                                       hwDeviceExtension);
        !          4836: 
        !          4837:         //
        !          4838:         // Write back the real value of the sequencer address port.
        !          4839:         //
        !          4840: 
        !          4841:         VideoPortWritePortUchar(hwDeviceExtension->IOAddress +
        !          4842:                                     SEQ_ADDRESS_PORT,
        !          4843:                                 (UCHAR) hwDeviceExtension->SequencerAddressValue);
        !          4844: 
        !          4845:         //
        !          4846:         // If we are in a READ path, read the data
        !          4847:         //
        !          4848: 
        !          4849:         if (AccessMode & EMULATOR_READ_ACCESS) {
        !          4850: 
        !          4851:             *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
        !          4852:                                                Port));
        !          4853: 
        !          4854:             endEmulation = 0;
        !          4855: 
        !          4856:         }
        !          4857: 
        !          4858:         //
        !          4859:         // If we are ending emulation, reset trapping to the minimal amount
        !          4860:         // and exit.
        !          4861:         //
        !          4862: 
        !          4863:         if (endEmulation) {
        !          4864: 
        !          4865:             VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
        !          4866:                                              NUM_MINIMAL_VGA_VALIDATOR_ACCESS_RANGE,
        !          4867:                                              MinimalVgaValidatorAccessRange);
        !          4868: 
        !          4869:             return NO_ERROR;
        !          4870: 
        !          4871:         }
        !          4872: 
        !          4873:         //
        !          4874:         // For both cases, put back a START_SYNC_RESET in the buffer.
        !          4875:         //
        !          4876: 
        !          4877:         hwDeviceExtension->TrappedValidatorCount = 1;
        !          4878: 
        !          4879:         hwDeviceExtension->TrappedValidatorData[0].Port = SEQ_ADDRESS_PORT;
        !          4880: 
        !          4881:         hwDeviceExtension->TrappedValidatorData[0].AccessType =
        !          4882:                 VGA_VALIDATOR_USHORT_ACCESS;
        !          4883: 
        !          4884:         hwDeviceExtension->TrappedValidatorData[0].Data =
        !          4885:                 (ULONG) (IND_SYNC_RESET + (START_SYNC_RESET_VALUE << 8));
        !          4886: 
        !          4887:     } else {
        !          4888: 
        !          4889:         //
        !          4890:         // Nothing trapped.
        !          4891:         // Lets check is the IO is trying to do something that would require
        !          4892:         // us to stop trapping
        !          4893:         //
        !          4894: 
        !          4895:         if (AccessMode & EMULATOR_WRITE_ACCESS) {
        !          4896: 
        !          4897:             //
        !          4898:             // Make sure Bit 3 of the Miscelaneous register is always 0.
        !          4899:             // If it is 1 it could select a non-existant clock, and kill the
        !          4900:             // system
        !          4901:             //
        !          4902: 
        !          4903:             if (Port == MISC_OUTPUT_REG_WRITE_PORT) {
        !          4904: 
        !          4905:                 temp = VideoPortReadPortUchar(hwDeviceExtension->IOAddress +
        !          4906:                                                   SEQ_ADDRESS_PORT);
        !          4907: 
        !          4908:                 VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
        !          4909:                                              SEQ_ADDRESS_PORT),
        !          4910:                                          (USHORT) (IND_SYNC_RESET +
        !          4911:                                              (START_SYNC_RESET_VALUE << 8)));
        !          4912: 
        !          4913:                 VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
        !          4914:                                              Port),
        !          4915:                                          (ULONG) (*Data & 0xFFFFFFF7) );
        !          4916: 
        !          4917:                 VideoPortWritePortUshort((PUSHORT) (hwDeviceExtension->IOAddress +
        !          4918:                                              SEQ_ADDRESS_PORT),
        !          4919:                                          (USHORT) (IND_SYNC_RESET +
        !          4920:                                              (END_SYNC_RESET_VALUE << 8)));
        !          4921: 
        !          4922:                 VideoPortWritePortUchar(hwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
        !          4923:                                         temp);
        !          4924: 
        !          4925:                 return NO_ERROR;
        !          4926: 
        !          4927:             }
        !          4928: 
        !          4929:             if ( (Port == SEQ_ADDRESS_PORT) &&
        !          4930:                  (((*Data>> 8) & END_SYNC_RESET_VALUE) != END_SYNC_RESET_VALUE) &&
        !          4931:                  ((*Data & 0xFF) == IND_SYNC_RESET)) {
        !          4932: 
        !          4933:                 VideoPortSetTrappedEmulatorPorts(hwDeviceExtension,
        !          4934:                                                  NUM_FULL_VGA_VALIDATOR_ACCESS_RANGE,
        !          4935:                                                  FullVgaValidatorAccessRange);
        !          4936: 
        !          4937:                 hwDeviceExtension->TrappedValidatorCount = 1;
        !          4938:                 hwDeviceExtension->TrappedValidatorData[0].Port = Port;
        !          4939:                 hwDeviceExtension->TrappedValidatorData[0].AccessType =
        !          4940:                     VGA_VALIDATOR_ULONG_ACCESS;
        !          4941: 
        !          4942:                 hwDeviceExtension->TrappedValidatorData[0].Data = *Data;
        !          4943: 
        !          4944:                 //
        !          4945:                 // Start keeping track of the state of the sequencer port.
        !          4946:                 //
        !          4947: 
        !          4948:                 hwDeviceExtension->SequencerAddressValue = IND_SYNC_RESET;
        !          4949: 
        !          4950:             } else {
        !          4951: 
        !          4952:                 VideoPortWritePortUlong((PULONG) (hwDeviceExtension->IOAddress +
        !          4953:                                             Port),
        !          4954:                                         *Data);
        !          4955: 
        !          4956:             }
        !          4957: 
        !          4958:         } else {
        !          4959: 
        !          4960:             *Data = VideoPortReadPortUlong((PULONG) (hwDeviceExtension->IOAddress +
        !          4961:                                            Port));
        !          4962: 
        !          4963:         }
        !          4964:     }
        !          4965: 
        !          4966:     return NO_ERROR;
        !          4967: 
        !          4968: } // end VgaValidatorUlongEntry()
        !          4969: 
        !          4970: 
        !          4971: //---------------------------------------------------------------------------
        !          4972: BOOLEAN
        !          4973: VgaPlaybackValidatorData(
        !          4974:     PVOID Context
        !          4975:     )
        !          4976: 
        !          4977: /*++
        !          4978: 
        !          4979: Routine Description:
        !          4980: 
        !          4981:     Performs all the DOS apps IO port accesses that were trapped by the
        !          4982:     validator. Only IO accesses that can be processed are WRITEs
        !          4983: 
        !          4984:     The number of outstanding IO access in deviceExtension is set to
        !          4985:     zero as a side effect.
        !          4986: 
        !          4987:     This function must be called via a call to VideoPortSynchronizeRoutine.
        !          4988: 
        !          4989: Arguments:
        !          4990: 
        !          4991:     Context - Context parameter passed to the synchronized routine.
        !          4992:         Must be a pointer to the miniport driver's device extension.
        !          4993: 
        !          4994: Return Value:
        !          4995: 
        !          4996:     TRUE.
        !          4997: 
        !          4998: --*/
        !          4999: 
        !          5000: {
        !          5001:     PHW_DEVICE_EXTENSION hwDeviceExtension = Context;
        !          5002:     ULONG ioBaseAddress = (ULONG) hwDeviceExtension->IOAddress;
        !          5003:     UCHAR i;
        !          5004:     PVGA_VALIDATOR_DATA validatorData = hwDeviceExtension->TrappedValidatorData;
        !          5005: 
        !          5006:     //
        !          5007:     // Loop through the array of data and do instructions one by one.
        !          5008:     //
        !          5009: 
        !          5010:     for (i = 0; i < hwDeviceExtension->TrappedValidatorCount;
        !          5011:          i++, validatorData++) {
        !          5012: 
        !          5013:         //
        !          5014:         // Calculate base address first
        !          5015:         //
        !          5016: 
        !          5017:         ioBaseAddress = (ULONG)hwDeviceExtension->IOAddress +
        !          5018:                             validatorData->Port;
        !          5019: 
        !          5020: 
        !          5021:         //
        !          5022:         // This is a write operation. We will automatically stop when the
        !          5023:         // buffer is empty.
        !          5024:         //
        !          5025: 
        !          5026:         switch (validatorData->AccessType) {
        !          5027: 
        !          5028:         case VGA_VALIDATOR_UCHAR_ACCESS :
        !          5029: 
        !          5030:             VideoPortWritePortUchar((PUCHAR)ioBaseAddress,
        !          5031:                                     (UCHAR) validatorData->Data);
        !          5032: 
        !          5033:             break;
        !          5034: 
        !          5035:         case VGA_VALIDATOR_USHORT_ACCESS :
        !          5036: 
        !          5037:             VideoPortWritePortUshort((PUSHORT)ioBaseAddress,
        !          5038:                                      (USHORT) validatorData->Data);
        !          5039: 
        !          5040:             break;
        !          5041: 
        !          5042:         case VGA_VALIDATOR_ULONG_ACCESS :
        !          5043: 
        !          5044:             VideoPortWritePortUlong((PULONG)ioBaseAddress,
        !          5045:                                     (ULONG) validatorData->Data);
        !          5046: 
        !          5047:             break;
        !          5048: 
        !          5049:         default:
        !          5050: 
        !          5051:             VideoDebugPrint((0, "InvalidValidatorAccessType\n" ));
        !          5052: 
        !          5053:         }
        !          5054:     }
        !          5055: 
        !          5056:     hwDeviceExtension->TrappedValidatorCount = 0;
        !          5057: 
        !          5058:     return TRUE;
        !          5059: 
        !          5060: } // end VgaPlaybackValidatorData()
        !          5061: 
        !          5062: 
        !          5063: //---------------------------------------------------------------------------
        !          5064: BOOLEAN
        !          5065: CirrusLogicIsPresent(
        !          5066:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !          5067:     )
        !          5068: 
        !          5069: /*++
        !          5070: 
        !          5071: Routine Description:
        !          5072: 
        !          5073:     This routine returns TRUE if an CL6410, 6420 or 542x is present. It 
        !          5074:     assumes that it's already been established that a VGA is present.  
        !          5075:     It performs the Cirrus Logic recommended ID test for each chip type:
        !          5076: 
        !          5077:     6410: we try to enable the extension registers and read back a 1, then 
        !          5078:     disable the extensions are read back a 0 in GR0A.
        !          5079: 
        !          5080:     6420: same as above
        !          5081: 
        !          5082:     542x: Enable extended registers by writing 0x12 to the extensions
        !          5083:           enable register, and reading back 0x12.  Then read from the 
        !          5084:           ID register and make sure it specifies a 5420, 5422, 5424,
        !          5085:           or 5426.  Finally, disable the extensions and make sure the
        !          5086:           extensions enable register reads back 0x0F.
        !          5087: 
        !          5088:     If this function fails to find an Cirrus Logic VGA, it attempts to undo any 
        !          5089:     damage it may have inadvertently done while testing.
        !          5090: 
        !          5091:     If a Cirrus Logic VGA is found, the adapter is returned to its original 
        !          5092:     state after testing is finished, except that extensions are left enabled.
        !          5093: 
        !          5094: Arguments:
        !          5095: 
        !          5096:     None.
        !          5097: 
        !          5098: Return Value:
        !          5099: 
        !          5100:     TRUE if an CL6410/6420/542x is present, FALSE if not.
        !          5101: 
        !          5102: --*/
        !          5103: 
        !          5104: {
        !          5105:     UCHAR originalGRIndex;
        !          5106:     UCHAR originalGR0A;
        !          5107:     UCHAR originalCRTCIndex;
        !          5108:     UCHAR originalSeqIndex;
        !          5109:     UCHAR originalExtsEnb;
        !          5110:     PUCHAR CRTCAddressPort, CRTCDataPort;
        !          5111:     UCHAR temp1, temp2, temp3;
        !          5112:     UCHAR revision;
        !          5113:     BOOLEAN retvalue = FALSE;    // default return value
        !          5114:     ULONG i;
        !          5115: 
        !          5116:     // first, save the Graphics controller index
        !          5117:     originalGRIndex = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5118:             GRAPH_ADDRESS_PORT);
        !          5119: 
        !          5120:     // Then save the value of GR0A
        !          5121:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5122:             GRAPH_ADDRESS_PORT, CL64xx_EXTENSION_ENABLE_INDEX);
        !          5123:     originalGR0A = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5124:             GRAPH_DATA_PORT);
        !          5125: 
        !          5126:     // then, Unlock the CL6410 extended registers., GR0A = 0ECH
        !          5127:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5128:             GRAPH_DATA_PORT, CL64xx_EXTENSION_ENABLE_VALUE);
        !          5129: 
        !          5130:     // read back GR0A, it should be a 1
        !          5131:     temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5132:             GRAPH_DATA_PORT);
        !          5133: 
        !          5134:     // then, Lock the CL6410 extended registers., GR0A = 0CEH
        !          5135:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5136:             GRAPH_DATA_PORT, CL64xx_EXTENSION_DISABLE_VALUE);
        !          5137: 
        !          5138:     // read back GR0A, it should be a 0
        !          5139:     temp2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5140:             GRAPH_DATA_PORT);
        !          5141: 
        !          5142:     // restore the GR0A value
        !          5143:     // this will not have any effect if the chip IS a CL6410 or 6420
        !          5144:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5145:             GRAPH_DATA_PORT, originalGR0A);
        !          5146: 
        !          5147:     // now restore the graphics index
        !          5148:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5149:             GRAPH_ADDRESS_PORT, originalGRIndex);
        !          5150: 
        !          5151:     // now test to see if the returned values were correct!
        !          5152:     // 
        !          5153:     if ((temp1 == 1) && (temp2 == 0)) {
        !          5154:     //
        !          5155:     // By golly, it *is* a CL6410 or CL6420!
        !          5156:     //
        !          5157:     // but now we have to determine the chip type, and which display is
        !          5158:     // active.
        !          5159: // reenable the extension registers first
        !          5160:         VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5161:             GRAPH_ADDRESS_PORT), CL64xx_EXTENSION_ENABLE_INDEX + 
        !          5162:             (CL64xx_EXTENSION_ENABLE_VALUE << 8));
        !          5163: 
        !          5164:     // now get the chip type at ERAA
        !          5165:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5166:             GRAPH_ADDRESS_PORT, 0xaa);
        !          5167: 
        !          5168:         revision = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5169:              GRAPH_DATA_PORT);
        !          5170: 
        !          5171:     // now restore the graphics index
        !          5172:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5173:          GRAPH_ADDRESS_PORT, originalGRIndex);
        !          5174: 
        !          5175:         if ((revision & 0xf0) == 0x80) {     // 6410 rev code
        !          5176:            VideoDebugPrint((1, "CL 6410 found\n"));
        !          5177: //
        !          5178: // we don't support 6340 in this driver, so force it not to be installed
        !          5179: //
        !          5180:             if (!CirrusFind6340(HwDeviceExtension)) {
        !          5181:                HwDeviceExtension->ChipType = CL6410;
        !          5182:                HwDeviceExtension->AdapterMemorySize = 0x00040000; // 256K
        !          5183:                HwDeviceExtension->DisplayType = 
        !          5184:                                     CirrusFind6410DisplayType(HwDeviceExtension);
        !          5185:                retvalue = TRUE;
        !          5186:                }
        !          5187:             }
        !          5188:         else if ((revision & 0xf0) == 0x70) {          // 6420 rev code
        !          5189:            VideoDebugPrint((1, "CL 6420 found\n"));
        !          5190: //
        !          5191: // we don't support 6340 in this driver, so force it not to be installed
        !          5192: //
        !          5193:             if (!CirrusFind6340(HwDeviceExtension)) {
        !          5194:                HwDeviceExtension->ChipType = CL6420;
        !          5195:                HwDeviceExtension->ChipRevision = (USHORT) revision;
        !          5196:                HwDeviceExtension->AdapterMemorySize = 
        !          5197:                                     CirrusFindVmemSize(HwDeviceExtension);
        !          5198:                HwDeviceExtension->DisplayType = 
        !          5199:                                     CirrusFind6410DisplayType(HwDeviceExtension);
        !          5200:                retvalue = TRUE;
        !          5201:                }
        !          5202:             }
        !          5203:         else { // we dont support 5410 at this time
        !          5204: 
        !          5205:           VideoDebugPrint((1, "Unsupported CL VGA chip found\n"));
        !          5206: //          retvalue = FALSE;          // already FALSE
        !          5207:             }
        !          5208:         }
        !          5209:    if (!retvalue)          // Did not detect a 64x0, see if it's a 542x
        !          5210:       {
        !          5211:       //
        !          5212:       // Determine where the CRTC registers are addressed (color or mono).
        !          5213:       //
        !          5214:       CRTCAddressPort = HwDeviceExtension->IOAddress;
        !          5215:       CRTCDataPort = HwDeviceExtension->IOAddress;
        !          5216: 
        !          5217:       if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5218:                   MISC_OUTPUT_REG_READ_PORT) & 0x01) {
        !          5219: 
        !          5220:           CRTCAddressPort += CRTC_ADDRESS_PORT_COLOR;
        !          5221:           CRTCDataPort += CRTC_DATA_PORT_COLOR;
        !          5222: 
        !          5223:       } else {
        !          5224: 
        !          5225:           CRTCAddressPort += CRTC_ADDRESS_PORT_MONO;
        !          5226:           CRTCDataPort += CRTC_DATA_PORT_MONO;
        !          5227:       }
        !          5228:       //
        !          5229:       // Save the original state of the CRTC and Sequencer Indices.
        !          5230:       //
        !          5231:       originalCRTCIndex = VideoPortReadPortUchar(CRTCAddressPort);
        !          5232:       originalSeqIndex =  VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5233:                           SEQ_ADDRESS_PORT);
        !          5234:       //
        !          5235:       // Try to enable all extensions:
        !          5236:       // a) Set the Sequencer Index to IND_CL_EXTS_ENB.
        !          5237:       //
        !          5238:       VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
        !          5239:                               IND_CL_EXTS_ENB);
        !          5240:       //
        !          5241:       // b) Save the original state of Sequencer register IND_CL_EXTS_ENB.
        !          5242:       //
        !          5243:       originalExtsEnb = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5244:                         SEQ_ADDRESS_PORT);
        !          5245:       //
        !          5246:       // c) Write enabling value (0x12) to extension enable register
        !          5247:       //
        !          5248:       VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5249:               SEQ_ADDRESS_PORT),(USHORT)((0x12 << 8) + IND_CL_EXTS_ENB));
        !          5250:       VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
        !          5251:               IND_CL_EXTS_ENB);
        !          5252:       temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5253:               SEQ_DATA_PORT);
        !          5254:       //
        !          5255:       // Read Chip ID Value from CRTC Register (Ignoring revision bits)
        !          5256:       //
        !          5257:       VideoPortWritePortUchar(CRTCAddressPort, IND_CL_ID_REG);
        !          5258:       temp3 = (VideoPortReadPortUchar(CRTCDataPort) & 0xFC);
        !          5259:       //
        !          5260:       // Write another value (!= 0x12) to IND_CL_EXTS_ENB to disable extensions
        !          5261:       // Should read back as 0x0F
        !          5262:       //
        !          5263:       VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5264:               SEQ_ADDRESS_PORT),(USHORT)((0 << 8) + IND_CL_EXTS_ENB));
        !          5265:       VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
        !          5266:               IND_CL_EXTS_ENB);
        !          5267:       temp2 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5268:               SEQ_DATA_PORT);
        !          5269:       //
        !          5270:       // Restore the original IND_CL_EXTS_ENB state.
        !          5271:       //
        !          5272: 
        !          5273:       VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress 
        !          5274:             + SEQ_ADDRESS_PORT),
        !          5275:               (USHORT)((originalExtsEnb << 8) + IND_CL_EXTS_ENB));
        !          5276:       //
        !          5277:       // Restore the original Sequencer and CRTC Indices.
        !          5278:       //
        !          5279:       VideoPortWritePortUchar((HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT),
        !          5280:               originalSeqIndex);
        !          5281:       VideoPortWritePortUchar(CRTCAddressPort, originalCRTCIndex);
        !          5282:       //
        !          5283:       // Check values read from IND_CL_EXTS_ENB and IND_CL_ID_REG to be correct
        !          5284:       //
        !          5285:       if ((temp1 != (UCHAR) (0x12)) ||
        !          5286:           (temp2 != (UCHAR) (0x0F)) ||
        !          5287:           (temp3 >  (UCHAR) (0x26 << 2))    ||       // 26 is 5428
        !          5288:           (temp3 <  (UCHAR) (0x22 << 2)))     {      // 22 is 5420
        !          5289:           //
        !          5290:           // Did not find appropriate CL VGA Chip.
        !          5291:           //
        !          5292: 
        !          5293:           VideoDebugPrint((1, "CL VGA chip not found\n"));
        !          5294: 
        !          5295:           retvalue = FALSE;
        !          5296: 
        !          5297:       }
        !          5298:       else {
        !          5299:     //
        !          5300:     // It's a supported CL adapter.
        !          5301:     //
        !          5302:            VideoDebugPrint((1, "CL 542x found\n"));
        !          5303:            HwDeviceExtension->ChipType = CL542x;
        !          5304:            HwDeviceExtension->DisplayType = crt;
        !          5305:            HwDeviceExtension->AdapterMemorySize = 
        !          5306:                CirrusFindVmemSize(HwDeviceExtension);
        !          5307: 
        !          5308:            retvalue = TRUE;
        !          5309:       }
        !          5310:    }
        !          5311: 
        !          5312:     //
        !          5313:     // Determines whic modes are valid.
        !          5314:     //
        !          5315: 
        !          5316:     if (retvalue) {
        !          5317: 
        !          5318:         CirrusValidateModes(HwDeviceExtension);
        !          5319: 
        !          5320:     }
        !          5321: 
        !          5322:    return retvalue;
        !          5323: 
        !          5324: } // CirrusLogicIsPresent()
        !          5325: 
        !          5326: //---------------------------------------------------------------------------
        !          5327: ULONG
        !          5328: CirrusFindVmemSize(
        !          5329:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !          5330:     )
        !          5331: 
        !          5332: /*++
        !          5333: 
        !          5334: Routine Description:
        !          5335: 
        !          5336:     This routine returns the amount of vram detected for the
        !          5337:     Cirrus Logic 6420 and 542x ONLY. It assumes that it is already known that
        !          5338:     a Cirrus Logic VGA is in the system.
        !          5339: 
        !          5340: Arguments:
        !          5341: 
        !          5342:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          5343: 
        !          5344: Return Value:
        !          5345: 
        !          5346:     Number of butes of VRAM.
        !          5347: 
        !          5348: --*/
        !          5349: {
        !          5350: 
        !          5351:     UCHAR temp;
        !          5352:     ULONG memsize;
        !          5353:     UCHAR originalSeqIndex;
        !          5354:     UCHAR originalGraphicsIndex;
        !          5355:     UCHAR PostScratchPad;
        !          5356: 
        !          5357:     if (HwDeviceExtension->ChipType == CL6420) {
        !          5358: 
        !          5359:         originalGraphicsIndex = 
        !          5360:             VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
        !          5361:                                    GRAPH_ADDRESS_PORT));
        !          5362: 
        !          5363:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5364:                                 GRAPH_ADDRESS_PORT, 0x9a); // Video memory config register
        !          5365: 
        !          5366:         temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5367:                                       GRAPH_DATA_PORT);    // get the data
        !          5368: 
        !          5369:         if ((temp & 0x07) == 0) { // 0 is accurate always
        !          5370: 
        !          5371:              memsize = 0x00040000;
        !          5372: 
        !          5373:         } else {
        !          5374: 
        !          5375:             //
        !          5376:             // We know now that the amount of vram is >256k. But we don't
        !          5377:             // know if it is 512k or 1meg. 
        !          5378:             // They tell us to actually go out and see if memory is there by
        !          5379:             // writing into it and reading it back.
        !          5380:             //
        !          5381: 
        !          5382:             VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress + 
        !          5383:                                      SEQ_ADDRESS_PORT),0x0f02);
        !          5384: 
        !          5385:             VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress + 
        !          5386:                                      GRAPH_ADDRESS_PORT),0x0506);
        !          5387: 
        !          5388:             //
        !          5389:             // now pick a bank, and do the write
        !          5390:             //
        !          5391: 
        !          5392:             SetCirrusBanking(HwDeviceExtension,1);        // start of 2nd 256k
        !          5393: 
        !          5394:             VideoPortWriteRegisterUchar(HwDeviceExtension->VideoMemoryAddress,
        !          5395:                                         0x55);
        !          5396: 
        !          5397:             SetCirrusBanking(HwDeviceExtension,3);    // 3*256k is 768k
        !          5398:     
        !          5399:             VideoPortWriteRegisterUchar(HwDeviceExtension->VideoMemoryAddress,
        !          5400:                                         0xaa);
        !          5401: 
        !          5402:             SetCirrusBanking(HwDeviceExtension,1);        // start of 2nd 256k
        !          5403: 
        !          5404:             if (VideoPortReadRegisterUchar(HwDeviceExtension->VideoMemoryAddress)
        !          5405:                     == 0x55)  {
        !          5406: 
        !          5407:                 memsize = 0x00100000; // 1 MEG
        !          5408: 
        !          5409:             } else {
        !          5410: 
        !          5411:                 memsize = 0x00080000; // 512K
        !          5412: 
        !          5413:             }
        !          5414: 
        !          5415:             SetCirrusBanking(HwDeviceExtension,0);    // reset the memory value
        !          5416: 
        !          5417:             VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
        !          5418: 
        !          5419:             VideoPortWritePortUchar((HwDeviceExtension->IOAddress 
        !          5420:                                     + GRAPH_ADDRESS_PORT),
        !          5421:                                     originalGraphicsIndex);
        !          5422: 
        !          5423: 
        !          5424:         }
        !          5425:  
        !          5426:         VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
        !          5427:                                    GRAPH_ADDRESS_PORT), originalGraphicsIndex);
        !          5428: 
        !          5429:         return memsize;
        !          5430: 
        !          5431:    } else {   // its 542x
        !          5432: 
        !          5433:         originalSeqIndex = VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
        !          5434:                                                   SEQ_ADDRESS_PORT));
        !          5435: 
        !          5436:         VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5437:                                  SEQ_ADDRESS_PORT),
        !          5438:                                  (USHORT)((0x12 << 8) + IND_CL_EXTS_ENB));
        !          5439: 
        !          5440:         //
        !          5441:         // Read the POST scratch pad reg SR0A to determine amount of Video
        !          5442:         // memory
        !          5443:         //
        !          5444: 
        !          5445:         VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
        !          5446:                                 IND_CL_SCRATCH_PAD);
        !          5447: 
        !          5448:         PostScratchPad = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5449:                                                 SEQ_DATA_PORT);
        !          5450: 
        !          5451:         VideoPortWritePortUchar((HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT),
        !          5452:                                 originalSeqIndex);
        !          5453: 
        !          5454:         //
        !          5455:         // Installed video memory is stored in scratch pad register by POST.
        !          5456:         //
        !          5457: 
        !          5458:         switch (PostScratchPad & 0x18) {  // It's in bits 3 and 4
        !          5459: 
        !          5460:         case 0x00:
        !          5461: 
        !          5462:             return 0x00040000; // 256K
        !          5463:             break;
        !          5464: 
        !          5465:         case 0x08:
        !          5466: 
        !          5467:             return 0x00080000; // 512K
        !          5468:             break;
        !          5469: 
        !          5470:         case 0x10:
        !          5471:             return 0x00100000; // 1 MEG
        !          5472:             break;
        !          5473: 
        !          5474:         case 0x18:
        !          5475:             return 0x00200000; // 2 MEG
        !          5476:             break;
        !          5477: 
        !          5478:         }
        !          5479: 
        !          5480:     }
        !          5481: 
        !          5482: } // CirrusFindVmemSize()
        !          5483: 
        !          5484: //---------------------------------------------------------------------------
        !          5485: VOID
        !          5486: SetCirrusBanking(
        !          5487:     PHW_DEVICE_EXTENSION HwDeviceExtension,
        !          5488:     USHORT BankNumber
        !          5489:     )
        !          5490: /*++
        !          5491: 
        !          5492: Routine Description:
        !          5493: 
        !          5494: Arguments:
        !          5495: 
        !          5496:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          5497: 
        !          5498:     BankNumber - the 256k bank number to set in 1RW mode(we will set this mode).
        !          5499: 
        !          5500: Return Value:
        !          5501: 
        !          5502:     vmem256k, vmem512k, or vmem1Meg ONLY ( these are defined in cirrus.h).
        !          5503: 
        !          5504: --*/
        !          5505: {
        !          5506: 
        !          5507:     if (HwDeviceExtension->ChipType == CL542x) {
        !          5508: 
        !          5509:         VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          5510:                                  GRAPH_ADDRESS_PORT), 0x1206);
        !          5511:  
        !          5512:         VideoPortWritePortUshort((PUSHORT) (HwDeviceExtension->IOAddress +
        !          5513:                                  GRAPH_ADDRESS_PORT), 0x010b);
        !          5514:  
        !          5515:         VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5516:                                  GRAPH_ADDRESS_PORT),
        !          5517:                                  (USHORT)(0x0009 + (BankNumber << (8+4))) );
        !          5518: 
        !          5519:     } else { // 6410 or 6420
        !          5520: 
        !          5521:         VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5522:                                  GRAPH_ADDRESS_PORT), 0xec0a);
        !          5523:  
        !          5524:         VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5525:                                  GRAPH_ADDRESS_PORT), 0x030d);
        !          5526:  
        !          5527:         VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress +
        !          5528:                                  GRAPH_ADDRESS_PORT),
        !          5529:                                  (USHORT)(0x000e + (BankNumber << (8+4))) );
        !          5530: 
        !          5531:     }
        !          5532: 
        !          5533: } // SetCirrusBanking()
        !          5534: 
        !          5535: //---------------------------------------------------------------------------
        !          5536: USHORT
        !          5537: CirrusFind6410DisplayType(
        !          5538:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !          5539:     )
        !          5540: 
        !          5541: /*++
        !          5542: 
        !          5543: Routine Description:
        !          5544: 
        !          5545:    Determines the display type for CL6410 or CL6420 crt/panel controllers.
        !          5546: Arguments:
        !          5547: 
        !          5548:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          5549: 
        !          5550: Return Value:
        !          5551: 
        !          5552:     crt, panel, (no simulscan yet) as defined in cirrus.h
        !          5553: 
        !          5554: --*/
        !          5555: {
        !          5556:     UCHAR originalGraphicsIndex;
        !          5557:     UCHAR temp1;
        !          5558: 
        !          5559:     //
        !          5560:     // now we need to check to see which display we are on...
        !          5561:     //
        !          5562: 
        !          5563:     originalGraphicsIndex = 
        !          5564:         VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
        !          5565:                                GRAPH_ADDRESS_PORT));
        !          5566: 
        !          5567:     VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5568:         GRAPH_ADDRESS_PORT, 0xd6);
        !          5569:  
        !          5570:     temp1 = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5571:                                    GRAPH_DATA_PORT);
        !          5572: 
        !          5573:     VideoPortWritePortUchar((HwDeviceExtension->IOAddress 
        !          5574:                             + GRAPH_ADDRESS_PORT), originalGraphicsIndex);
        !          5575: 
        !          5576: 
        !          5577:     if (temp1 & 0x02) {  // display is LCD Panel(or simulscan)
        !          5578: 
        !          5579:         return panel;
        !          5580: 
        !          5581:     } else {              // the display is a crt
        !          5582: 
        !          5583:         return crt;
        !          5584: 
        !          5585:     }
        !          5586: 
        !          5587: } // CirrusFind6410DisplayType()
        !          5588: 
        !          5589: //---------------------------------------------------------------------------
        !          5590: BOOLEAN
        !          5591: CirrusFind6340(
        !          5592:     PHW_DEVICE_EXTENSION HwDeviceExtension
        !          5593:     )
        !          5594: /*++
        !          5595: 
        !          5596: Routine Description:
        !          5597: 
        !          5598:    Determines if a CL6340 (Peacock) Color LCD controller is in the system
        !          5599:    along with a 6410 or 6420.
        !          5600: 
        !          5601:    Assumes that a 6410 or 6420 is already in the system.
        !          5602: 
        !          5603: Arguments:
        !          5604: 
        !          5605:     HwDeviceExtension - Pointer to the miniport driver's device extension.
        !          5606: 
        !          5607: Return Value:
        !          5608: 
        !          5609:     TRUE,   6340 detected
        !          5610:     FALSE,  6340 not detected
        !          5611: 
        !          5612: --*/
        !          5613: {
        !          5614: UCHAR originalGraphicsIndex;
        !          5615: UCHAR originalSRIndex;
        !          5616: UCHAR GRA1value;
        !          5617: UCHAR temp1,temp2;
        !          5618: 
        !          5619:    originalGraphicsIndex = 
        !          5620:       VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
        !          5621:       GRAPH_ADDRESS_PORT));
        !          5622: 
        !          5623:    originalSRIndex = 
        !          5624:       VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
        !          5625:       SEQ_ADDRESS_PORT));
        !          5626: 
        !          5627:    VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5628:       GRAPH_ADDRESS_PORT, CL64xx_TRISTATE_CONTROL_REG);
        !          5629:  
        !          5630:    GRA1value = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
        !          5631:       GRAPH_DATA_PORT);
        !          5632: 
        !          5633:    VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5634:       GRAPH_DATA_PORT, (UCHAR) (0x80 | GRA1value));
        !          5635: 
        !          5636:    VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress + 
        !          5637:       SEQ_ADDRESS_PORT), (USHORT) CL6340_ENABLE_READBACK_REGISTER + 
        !          5638:       (CL6340_ENABLE_READBACK_ALLSEL_VALUE << 8));
        !          5639: 
        !          5640:    VideoPortWritePortUchar((HwDeviceExtension->IOAddress + 
        !          5641:       SEQ_ADDRESS_PORT), CL6340_IDENTIFICATION_REGISTER);
        !          5642: 
        !          5643:    temp1 = VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
        !          5644:       SEQ_DATA_PORT));
        !          5645: 
        !          5646:    temp2 = VideoPortReadPortUchar((HwDeviceExtension->IOAddress +
        !          5647:       SEQ_DATA_PORT));
        !          5648: 
        !          5649:    VideoPortWritePortUshort((PUSHORT)(HwDeviceExtension->IOAddress + 
        !          5650:       SEQ_ADDRESS_PORT), (USHORT) CL6340_ENABLE_READBACK_REGISTER + 
        !          5651:       (CL6340_ENABLE_READBACK_OFF_VALUE << 8));
        !          5652: 
        !          5653: // Graphics index still points to CL64xx_TRISTATE_CONTROL_REG
        !          5654:    VideoPortWritePortUchar(HwDeviceExtension->IOAddress +
        !          5655:       GRAPH_DATA_PORT, (UCHAR) (0x7f & GRA1value));
        !          5656: 
        !          5657: // now restore the Graphics and Sequencer indexes
        !          5658:       VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
        !          5659:       GRAPH_ADDRESS_PORT),originalGraphicsIndex);
        !          5660: 
        !          5661:       VideoPortWritePortUchar((HwDeviceExtension->IOAddress +
        !          5662:       SEQ_ADDRESS_PORT),originalSRIndex);
        !          5663: 
        !          5664: // check the values for value peacock data
        !          5665:    if ( ((temp1 & 0xf0) == 0x70 && (temp2 & 0xf0) == 0x80) ||
        !          5666:         ((temp1 & 0xf0) == 0x80 && (temp2 & 0xf0) == 0x70)  )
        !          5667:       return TRUE;
        !          5668:    else
        !          5669:       return FALSE;
        !          5670: 
        !          5671: } // CirrusFind6410DisplayType()
        !          5672: //---------------------------------------------------------------------------

unix.superglobalmegacorp.com

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