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