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