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