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