Annotation of ntddk/src/video/miniport/et4000/et4000.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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