|
|
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()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.