1 /*
2  * PROJECT:         ReactOS VGA Miniport Driver
3  * LICENSE:         Microsoft NT4 DDK Sample Code License
4  * FILE:            win32ss/drivers/miniport/vga_new/modeset.c
5  * PURPOSE:         Handles switching to Standard VGA Modes for compatible cards
6  * PROGRAMMERS:     Copyright (c) 1992  Microsoft Corporation
7  *                  ReactOS Portable Systems Group
8  */
9 
10 #include "vga.h"
11 
12 VP_STATUS
13 NTAPI
14 VgaInterpretCmdStream(
15     PHW_DEVICE_EXTENSION HwDeviceExtension,
16     PUSHORT pusCmdStream
17     );
18 
19 VP_STATUS
20 NTAPI
21 VgaSetMode(
22     PHW_DEVICE_EXTENSION HwDeviceExtension,
23     PVIDEO_MODE Mode,
24     ULONG ModeSize,
25 // eVb: 2.1 [SET MODE] - Add new output parameter for framebuffer update functionality
26     PULONG PhysPtrChange
27 // eVb: 2.1 [END]
28     );
29 
30 VP_STATUS
31 NTAPI
32 VgaQueryAvailableModes(
33     PHW_DEVICE_EXTENSION HwDeviceExtension,
34     PVIDEO_MODE_INFORMATION ModeInformation,
35     ULONG ModeInformationSize,
36     PULONG_PTR OutputSize
37     );
38 
39 VP_STATUS
40 NTAPI
41 VgaQueryNumberOfAvailableModes(
42     PHW_DEVICE_EXTENSION HwDeviceExtension,
43     PVIDEO_NUM_MODES NumModes,
44     ULONG NumModesSize,
45     PULONG_PTR OutputSize
46     );
47 
48 VP_STATUS
49 NTAPI
50 VgaQueryCurrentMode(
51     PHW_DEVICE_EXTENSION HwDeviceExtension,
52     PVIDEO_MODE_INFORMATION ModeInformation,
53     ULONG ModeInformationSize,
54     PULONG_PTR OutputSize
55     );
56 
57 VOID
58 NTAPI
59 VgaZeroVideoMemory(
60     PHW_DEVICE_EXTENSION HwDeviceExtension
61     );
62 
63 #if defined(ALLOC_PRAGMA)
64 #pragma alloc_text(PAGE,VgaInterpretCmdStream)
65 #pragma alloc_text(PAGE,VgaSetMode)
66 #pragma alloc_text(PAGE,VgaQueryAvailableModes)
67 #pragma alloc_text(PAGE,VgaQueryNumberOfAvailableModes)
68 #pragma alloc_text(PAGE,VgaZeroVideoMemory)
69 #endif
70 
71 //---------------------------------------------------------------------------
72 VP_STATUS
73 NTAPI
74 VgaInterpretCmdStream(
75     PHW_DEVICE_EXTENSION HwDeviceExtension,
76     PUSHORT pusCmdStream
77     )
78 
79 /*++
80 
81 Routine Description:
82 
83     Interprets the appropriate command array to set up VGA registers for the
84     requested mode. Typically used to set the VGA into a particular mode by
85     programming all of the registers
86 
87 Arguments:
88 
89     HwDeviceExtension - Pointer to the miniport driver's device extension.
90 
91     pusCmdStream - array of commands to be interpreted.
92 
93 Return Value:
94 
95     The status of the operation (can only fail on a bad command); TRUE for
96     success, FALSE for failure.
97 
98 --*/
99 
100 {
101     ULONG ulCmd;
102     ULONG_PTR ulPort;
103     UCHAR jValue;
104     USHORT usValue;
105     ULONG culCount;
106     ULONG ulIndex;
107     ULONG_PTR ulBase;
108 
109     if (pusCmdStream == NULL) {
110 
111         VideoDebugPrint((1, "VgaInterpretCmdStream - Invalid pusCmdStream\n"));
112         return TRUE;
113     }
114 
115     ulBase = (ULONG_PTR)HwDeviceExtension->IOAddress;
116 
117     //
118     // Now set the adapter to the desired mode.
119     //
120 
121     while ((ulCmd = *pusCmdStream++) != EOD) {
122 
123         //
124         // Determine major command type
125         //
126 
127         switch (ulCmd & 0xF0) {
128 
129             //
130             // Basic input/output command
131             //
132 
133             case INOUT:
134 
135                 //
136                 // Determine type of inout instruction
137                 //
138 
139                 if (!(ulCmd & IO)) {
140 
141                     //
142                     // Out instruction. Single or multiple outs?
143                     //
144 
145                     if (!(ulCmd & MULTI)) {
146 
147                         //
148                         // Single out. Byte or word out?
149                         //
150 
151                         if (!(ulCmd & BW)) {
152 
153                             //
154                             // Single byte out
155                             //
156 
157                             ulPort = *pusCmdStream++;
158                             jValue = (UCHAR) *pusCmdStream++;
159                             VideoPortWritePortUchar((PUCHAR)(ulBase+ulPort),
160                                     jValue);
161 
162                         } else {
163 
164                             //
165                             // Single word out
166                             //
167 
168                             ulPort = *pusCmdStream++;
169                             usValue = *pusCmdStream++;
170                             VideoPortWritePortUshort((PUSHORT)(ulBase+ulPort),
171                                     usValue);
172 
173                         }
174 
175                     } else {
176 
177                         //
178                         // Output a string of values
179                         // Byte or word outs?
180                         //
181 
182                         if (!(ulCmd & BW)) {
183 
184                             //
185                             // String byte outs. Do in a loop; can't use
186                             // VideoPortWritePortBufferUchar because the data
187                             // is in USHORT form
188                             //
189 
190                             ulPort = ulBase + *pusCmdStream++;
191                             culCount = *pusCmdStream++;
192 
193                             while (culCount--) {
194                                 jValue = (UCHAR) *pusCmdStream++;
195                                 VideoPortWritePortUchar((PUCHAR)ulPort,
196                                         jValue);
197 
198                             }
199 
200                         } else {
201 
202                             //
203                             // String word outs
204                             //
205 
206                             ulPort = *pusCmdStream++;
207                             culCount = *pusCmdStream++;
208                             VideoPortWritePortBufferUshort((PUSHORT)
209                                     (ulBase + ulPort), pusCmdStream, culCount);
210                             pusCmdStream += culCount;
211 
212                         }
213                     }
214 
215                 } else {
216 
217                     // In instruction
218                     //
219                     // Currently, string in instructions aren't supported; all
220                     // in instructions are handled as single-byte ins
221                     //
222                     // Byte or word in?
223                     //
224 
225                     if (!(ulCmd & BW)) {
226                         //
227                         // Single byte in
228                         //
229 
230                         ulPort = *pusCmdStream++;
231                         jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort);
232 
233                     } else {
234 
235                         //
236                         // Single word in
237                         //
238 
239                         ulPort = *pusCmdStream++;
240                         usValue = VideoPortReadPortUshort((PUSHORT)
241                                 (ulBase+ulPort));
242 
243                     }
244 
245                 }
246 
247                 break;
248 
249             //
250             // Higher-level input/output commands
251             //
252 
253             case METAOUT:
254 
255                 //
256                 // Determine type of metaout command, based on minor
257                 // command field
258                 //
259                 switch (ulCmd & 0x0F) {
260 
261                     //
262                     // Indexed outs
263                     //
264 
265                     case INDXOUT:
266 
267                         ulPort = ulBase + *pusCmdStream++;
268                         culCount = *pusCmdStream++;
269                         ulIndex = *pusCmdStream++;
270 
271                         while (culCount--) {
272 
273                             usValue = (USHORT) (ulIndex +
274                                       (((ULONG)(*pusCmdStream++)) << 8));
275                             VideoPortWritePortUshort((PUSHORT)ulPort, usValue);
276 
277                             ulIndex++;
278 
279                         }
280 
281                         break;
282 
283                     //
284                     // Masked out (read, AND, XOR, write)
285                     //
286 
287                     case MASKOUT:
288 
289                         ulPort = *pusCmdStream++;
290                         jValue = VideoPortReadPortUchar((PUCHAR)ulBase+ulPort);
291                         jValue &= *pusCmdStream++;
292                         jValue ^= *pusCmdStream++;
293                         VideoPortWritePortUchar((PUCHAR)ulBase + ulPort,
294                                 jValue);
295                         break;
296 
297                     //
298                     // Attribute Controller out
299                     //
300 
301                     case ATCOUT:
302 
303                         ulPort = ulBase + *pusCmdStream++;
304                         culCount = *pusCmdStream++;
305                         ulIndex = *pusCmdStream++;
306 
307                         while (culCount--) {
308 
309                             // Write Attribute Controller index
310                             VideoPortWritePortUchar((PUCHAR)ulPort,
311                                     (UCHAR)ulIndex);
312 
313                             // Write Attribute Controller data
314                             jValue = (UCHAR) *pusCmdStream++;
315                             VideoPortWritePortUchar((PUCHAR)ulPort, jValue);
316 
317                             ulIndex++;
318 
319                         }
320 
321                         break;
322 
323                     //
324                     // None of the above; error
325                     //
326                     default:
327 
328                         return FALSE;
329 
330                 }
331 
332 
333                 break;
334 
335             //
336             // NOP
337             //
338 
339             case NCMD:
340 
341                 break;
342 
343             //
344             // Unknown command; error
345             //
346 
347             default:
348 
349                 return FALSE;
350 
351         }
352 
353     }
354 
355     return TRUE;
356 
357 } // end VgaInterpretCmdStream()
358 
359 VP_STATUS
360 NTAPI
361 VgaSetMode(
362     PHW_DEVICE_EXTENSION HwDeviceExtension,
363     PVIDEO_MODE Mode,
364     ULONG ModeSize,
365 // eVb: 2.2 [SET MODE] - Add new output parameter for framebuffer update functionality
366     PULONG PhysPtrChange
367 // eVb: 2.2 [END]
368     )
369 
370 /*++
371 
372 Routine Description:
373 
374     This routine sets the vga into the requested mode.
375 
376 Arguments:
377 
378     HwDeviceExtension - Pointer to the miniport driver's device extension.
379 
380     Mode - Pointer to the structure containing the information about the
381         font to be set.
382 
383     ModeSize - Length of the input buffer supplied by the user.
384 
385 Return Value:
386 
387     ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough
388         for the input data.
389 
390     ERROR_INVALID_PARAMETER if the mode number is invalid.
391 
392     NO_ERROR if the operation completed successfully.
393 
394 --*/
395 
396 {
397     PVIDEOMODE pRequestedMode;
398     VP_STATUS status;
399     ULONG RequestedModeNum;
400 // eVb: 2.3 [SET MODE] - Add new output parameter for framebuffer update functionality
401     *PhysPtrChange = FALSE;
402 // eVb: 2.3 [END]
403     //
404     // Check if the size of the data in the input buffer is large enough.
405     //
406 
407     if (ModeSize < sizeof(VIDEO_MODE))
408     {
409         return ERROR_INSUFFICIENT_BUFFER;
410     }
411 
412     //
413     // Extract the clear memory, and map linear bits.
414     //
415 
416     RequestedModeNum = Mode->RequestedMode &
417         ~(VIDEO_MODE_NO_ZERO_MEMORY | VIDEO_MODE_MAP_MEM_LINEAR);
418 
419 
420     if (!(Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY))
421     {
422 #if defined(_X86_)
423         VgaZeroVideoMemory(HwDeviceExtension);
424 #endif
425     }
426 
427     //
428     // Check to see if we are requesting a valid mode
429     //
430 // eVb: 2.4 [CIRRUS] - Remove Cirrus-specific check for valid mode
431     if ( (RequestedModeNum >= NumVideoModes) )
432 // eVb: 2.4 [END]
433     {
434         VideoDebugPrint((0, "Invalide Mode Number = %d!\n", RequestedModeNum));
435 
436         return ERROR_INVALID_PARAMETER;
437     }
438 
439     VideoDebugPrint((2, "Attempting to set mode %d\n",
440                         RequestedModeNum));
441 // eVb: 2.5 [VBE] - Use dynamic VBE mode list instead of hard-coded VGA list
442     pRequestedMode = &VgaModeList[RequestedModeNum];
443 // eVb: 2.5 [END]
444     VideoDebugPrint((2, "Info on Requested Mode:\n"
445                         "\tResolution: %dx%d\n",
446                         pRequestedMode->hres,
447                         pRequestedMode->vres ));
448 
449     //
450     // VESA BIOS mode switch
451     //
452 // eVb: 2.6 [VBE] - VBE Mode Switch Support
453     status = VbeSetMode(HwDeviceExtension, pRequestedMode, PhysPtrChange);
454     if (status == ERROR_INVALID_FUNCTION)
455     {
456         //
457         // VGA mode switch
458         //
459 
460         if (!pRequestedMode->CmdStream) return ERROR_INVALID_FUNCTION;
461         if (!VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStream)) return ERROR_INVALID_FUNCTION;
462         goto Cleanup;
463     }
464     else if (status != NO_ERROR) return status;
465 // eVb: 2.6 [END]
466 // eVb: 2.7 [MODE-X] - Windows VGA Miniport Supports Mode-X, we should too
467     //
468     // ModeX check
469     //
470 
471     if (pRequestedMode->hres == 320)
472     {
473         VideoDebugPrint((0, "ModeX not support!!!\n"));
474         return ERROR_INVALID_PARAMETER;
475     }
476 // eVb: 2.7 [END]
477     //
478     // Text mode check
479     //
480 
481     if (!(pRequestedMode->fbType & VIDEO_MODE_GRAPHICS))
482     {
483 // eVb: 2.8 [TODO] - This code path is not implemented yet
484         VideoDebugPrint((0, "Text-mode not support!!!\n"));
485         return ERROR_INVALID_PARAMETER;
486 // eVb: 2.8 [END]
487     }
488 
489 Cleanup:
490     //
491     // Update the location of the physical frame buffer within video memory.
492     //
493 // eVb: 2.9 [VBE] - Linear and banked support is unified in VGA, unlike Cirrus
494     HwDeviceExtension->PhysicalVideoMemoryBase.LowPart = pRequestedMode->PhysBase;
495     HwDeviceExtension->PhysicalVideoMemoryLength = pRequestedMode->PhysSize;
496 
497     HwDeviceExtension->PhysicalFrameLength =
498             pRequestedMode->FrameBufferSize;
499 
500     HwDeviceExtension->PhysicalFrameOffset.LowPart =
501             pRequestedMode->FrameBufferBase;
502 // eVb: 2.9 [END]
503 
504     //
505     // Store the new mode value.
506     //
507 
508     HwDeviceExtension->CurrentMode = pRequestedMode;
509     HwDeviceExtension->ModeIndex = Mode->RequestedMode;
510 
511     return NO_ERROR;
512 
513 } //end VgaSetMode()
514 
515 VP_STATUS
516 NTAPI
517 VgaQueryAvailableModes(
518     PHW_DEVICE_EXTENSION HwDeviceExtension,
519     PVIDEO_MODE_INFORMATION ModeInformation,
520     ULONG ModeInformationSize,
521     PULONG_PTR OutputSize
522     )
523 
524 /*++
525 
526 Routine Description:
527 
528     This routine returns the list of all available available modes on the
529     card.
530 
531 Arguments:
532 
533     HwDeviceExtension - Pointer to the miniport driver's device extension.
534 
535     ModeInformation - Pointer to the output buffer supplied by the user.
536         This is where the list of all valid modes is stored.
537 
538     ModeInformationSize - Length of the output buffer supplied by the user.
539 
540     OutputSize - Pointer to a buffer in which to return the actual size of
541         the data in the buffer. If the buffer was not large enough, this
542         contains the minimum required buffer size.
543 
544 Return Value:
545 
546     ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
547         for the data being returned.
548 
549     NO_ERROR if the operation completed successfully.
550 
551 --*/
552 
553 {
554     PVIDEO_MODE_INFORMATION videoModes = ModeInformation;
555     ULONG i;
556 
557     //
558     // Find out the size of the data to be put in the buffer and return
559     // that in the status information (whether or not the information is
560     // there). If the buffer passed in is not large enough return an
561     // appropriate error code.
562     //
563 
564     if (ModeInformationSize < (*OutputSize =
565 // eVb: 2.10 [VBE] - We store VBE/VGA mode count in this global, not in DevExt like Cirrus
566             NumVideoModes *
567 // eVb: 2.10 [END]
568             sizeof(VIDEO_MODE_INFORMATION)) ) {
569 
570         return ERROR_INSUFFICIENT_BUFFER;
571 
572     }
573 
574     //
575     // For each mode supported by the card, store the mode characteristics
576     // in the output buffer.
577     //
578 
579     for (i = 0; i < NumVideoModes; i++)
580     {
581         videoModes->Length = sizeof(VIDEO_MODE_INFORMATION);
582         videoModes->ModeIndex  = i;
583 // eVb: 2.11 [VBE] - Use dynamic VBE mode list instead of hard-coded VGA list
584         videoModes->VisScreenWidth = VgaModeList[i].hres;
585         videoModes->ScreenStride = VgaModeList[i].wbytes;
586         videoModes->VisScreenHeight = VgaModeList[i].vres;
587         videoModes->NumberOfPlanes = VgaModeList[i].numPlanes;
588         videoModes->BitsPerPlane = VgaModeList[i].bitsPerPlane;
589         videoModes->Frequency = VgaModeList[i].Frequency;
590         videoModes->XMillimeter = 320;        // temporary hardcoded constant
591         videoModes->YMillimeter = 240;        // temporary hardcoded constant
592         videoModes->AttributeFlags = VgaModeList[i].fbType;
593 // eVb: 2.11 [END]
594 
595         if ((VgaModeList[i].bitsPerPlane == 32) ||
596             (VgaModeList[i].bitsPerPlane == 24))
597         {
598 
599             videoModes->NumberRedBits = 8;
600             videoModes->NumberGreenBits = 8;
601             videoModes->NumberBlueBits = 8;
602             videoModes->RedMask = 0xff0000;
603             videoModes->GreenMask = 0x00ff00;
604             videoModes->BlueMask = 0x0000ff;
605 
606         }
607         else if (VgaModeList[i].bitsPerPlane == 16)
608         {
609 
610             videoModes->NumberRedBits = 6;
611             videoModes->NumberGreenBits = 6;
612             videoModes->NumberBlueBits = 6;
613             videoModes->RedMask = 0x1F << 11;
614             videoModes->GreenMask = 0x3F << 5;
615             videoModes->BlueMask = 0x1F;
616 
617         }
618 // eVb: 2.12 [VGA] - Add support for 15bpp modes, which Cirrus doesn't support
619         else if (VgaModeList[i].bitsPerPlane == 15)
620         {
621 
622             videoModes->NumberRedBits = 6;
623             videoModes->NumberGreenBits = 6;
624             videoModes->NumberBlueBits = 6;
625             videoModes->RedMask = 0x3E << 9;
626             videoModes->GreenMask = 0x1F << 5;
627             videoModes->BlueMask = 0x1F;
628         }
629 // eVb: 2.12 [END]
630         else
631         {
632 
633             videoModes->NumberRedBits = 6;
634             videoModes->NumberGreenBits = 6;
635             videoModes->NumberBlueBits = 6;
636             videoModes->RedMask = 0;
637             videoModes->GreenMask = 0;
638             videoModes->BlueMask = 0;
639         }
640 
641 // eVb: 2.13 [VGA] - All modes are palette managed/driven, unlike Cirrus
642         videoModes->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN |
643              VIDEO_MODE_MANAGED_PALETTE;
644 // eVb: 2.13 [END]
645         videoModes++;
646 
647     }
648 
649     return NO_ERROR;
650 
651 } // end VgaGetAvailableModes()
652 
653 VP_STATUS
654 NTAPI
655 VgaQueryNumberOfAvailableModes(
656     PHW_DEVICE_EXTENSION HwDeviceExtension,
657     PVIDEO_NUM_MODES NumModes,
658     ULONG NumModesSize,
659     PULONG_PTR OutputSize
660     )
661 
662 /*++
663 
664 Routine Description:
665 
666     This routine returns the number of available modes for this particular
667     video card.
668 
669 Arguments:
670 
671     HwDeviceExtension - Pointer to the miniport driver's device extension.
672 
673     NumModes - Pointer to the output buffer supplied by the user. This is
674         where the number of modes is stored.
675 
676     NumModesSize - Length of the output buffer supplied by the user.
677 
678     OutputSize - Pointer to a buffer in which to return the actual size of
679         the data in the buffer.
680 
681 Return Value:
682 
683     ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
684         for the data being returned.
685 
686     NO_ERROR if the operation completed successfully.
687 
688 --*/
689 
690 {
691     //
692     // Find out the size of the data to be put in the the buffer and return
693     // that in the status information (whether or not the information is
694     // there). If the buffer passed in is not large enough return an
695     // appropriate error code.
696     //
697 
698     if (NumModesSize < (*OutputSize = sizeof(VIDEO_NUM_MODES)) ) {
699 
700         return ERROR_INSUFFICIENT_BUFFER;
701 
702     }
703 
704     //
705     // Store the number of modes into the buffer.
706     //
707 
708 // eVb: 2.14 [VBE] - We store VBE/VGA mode count in this global, not in DevExt like Cirrus
709     NumModes->NumModes = NumVideoModes;
710 // eVb: 2.14 [END]
711     NumModes->ModeInformationLength = sizeof(VIDEO_MODE_INFORMATION);
712 
713     return NO_ERROR;
714 
715 } // end VgaGetNumberOfAvailableModes()
716 
717 VP_STATUS
718 NTAPI
719 VgaQueryCurrentMode(
720     PHW_DEVICE_EXTENSION HwDeviceExtension,
721     PVIDEO_MODE_INFORMATION ModeInformation,
722     ULONG ModeInformationSize,
723     PULONG_PTR OutputSize
724     )
725 
726 /*++
727 
728 Routine Description:
729 
730     This routine returns a description of the current video mode.
731 
732 Arguments:
733 
734     HwDeviceExtension - Pointer to the miniport driver's device extension.
735 
736     ModeInformation - Pointer to the output buffer supplied by the user.
737         This is where the current mode information is stored.
738 
739     ModeInformationSize - Length of the output buffer supplied by the user.
740 
741     OutputSize - Pointer to a buffer in which to return the actual size of
742         the data in the buffer. If the buffer was not large enough, this
743         contains the minimum required buffer size.
744 
745 Return Value:
746 
747     ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
748         for the data being returned.
749 
750     NO_ERROR if the operation completed successfully.
751 
752 --*/
753 
754 {
755     //
756     // check if a mode has been set
757     //
758 
759     if (HwDeviceExtension->CurrentMode == NULL ) {
760 
761         return ERROR_INVALID_FUNCTION;
762 
763     }
764 
765     //
766     // Find out the size of the data to be put in the the buffer and return
767     // that in the status information (whether or not the information is
768     // there). If the buffer passed in is not large enough return an
769     // appropriate error code.
770     //
771 
772     if (ModeInformationSize < (*OutputSize = sizeof(VIDEO_MODE_INFORMATION))) {
773 
774         return ERROR_INSUFFICIENT_BUFFER;
775 
776     }
777 
778     //
779     // Store the characteristics of the current mode into the buffer.
780     //
781 
782     ModeInformation->Length = sizeof(VIDEO_MODE_INFORMATION);
783     ModeInformation->ModeIndex = HwDeviceExtension->ModeIndex;
784     ModeInformation->VisScreenWidth = HwDeviceExtension->CurrentMode->hres;
785     ModeInformation->ScreenStride = HwDeviceExtension->CurrentMode->wbytes;
786     ModeInformation->VisScreenHeight = HwDeviceExtension->CurrentMode->vres;
787     ModeInformation->NumberOfPlanes = HwDeviceExtension->CurrentMode->numPlanes;
788     ModeInformation->BitsPerPlane = HwDeviceExtension->CurrentMode->bitsPerPlane;
789     ModeInformation->Frequency = HwDeviceExtension->CurrentMode->Frequency;
790     ModeInformation->XMillimeter = 320;        // temporary hardcoded constant
791     ModeInformation->YMillimeter = 240;        // temporary hardcoded constant
792 
793     ModeInformation->AttributeFlags = HwDeviceExtension->CurrentMode->fbType;
794 
795     if ((ModeInformation->BitsPerPlane == 32) ||
796         (ModeInformation->BitsPerPlane == 24))
797     {
798 
799         ModeInformation->NumberRedBits = 8;
800         ModeInformation->NumberGreenBits = 8;
801         ModeInformation->NumberBlueBits = 8;
802         ModeInformation->RedMask = 0xff0000;
803         ModeInformation->GreenMask = 0x00ff00;
804         ModeInformation->BlueMask = 0x0000ff;
805 
806     }
807     else if (ModeInformation->BitsPerPlane == 16)
808     {
809 
810         ModeInformation->NumberRedBits = 6;
811         ModeInformation->NumberGreenBits = 6;
812         ModeInformation->NumberBlueBits = 6;
813         ModeInformation->RedMask = 0x1F << 11;
814         ModeInformation->GreenMask = 0x3F << 5;
815         ModeInformation->BlueMask = 0x1F;
816 
817     }
818 // eVb: 2.12 [VGA] - Add support for 15bpp modes, which Cirrus doesn't support
819     else if (ModeInformation->BitsPerPlane == 15)
820     {
821 
822         ModeInformation->NumberRedBits = 6;
823         ModeInformation->NumberGreenBits = 6;
824         ModeInformation->NumberBlueBits = 6;
825         ModeInformation->RedMask = 0x3E << 9;
826         ModeInformation->GreenMask = 0x1F << 5;
827         ModeInformation->BlueMask = 0x1F;
828     }
829 // eVb: 2.12 [END]
830     else
831     {
832 
833         ModeInformation->NumberRedBits = 6;
834         ModeInformation->NumberGreenBits = 6;
835         ModeInformation->NumberBlueBits = 6;
836         ModeInformation->RedMask = 0;
837         ModeInformation->GreenMask = 0;
838         ModeInformation->BlueMask = 0;
839     }
840 
841 // eVb: 2.13 [VGA] - All modes are palette managed/driven, unlike Cirrus
842     ModeInformation->AttributeFlags |= VIDEO_MODE_PALETTE_DRIVEN |
843          VIDEO_MODE_MANAGED_PALETTE;
844 // eVb: 2.13 [END]
845 
846     return NO_ERROR;
847 
848 } // end VgaQueryCurrentMode()
849 
850 VOID
851 NTAPI
852 VgaZeroVideoMemory(
853     PHW_DEVICE_EXTENSION HwDeviceExtension
854     )
855 
856 /*++
857 
858 Routine Description:
859 
860     This routine zeros the first 256K on the VGA.
861 
862 Arguments:
863 
864     HwDeviceExtension - Pointer to the miniport driver's device extension.
865 
866 
867 Return Value:
868 
869     None.
870 
871 --*/
872 {
873     UCHAR temp;
874 
875     //
876     // Map font buffer at A0000
877     //
878 
879     VgaInterpretCmdStream(HwDeviceExtension, EnableA000Data);
880 
881     //
882     // Enable all planes.
883     //
884 
885     VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_ADDRESS_PORT,
886             IND_MAP_MASK);
887 
888     temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress +
889             SEQ_DATA_PORT) | (UCHAR)0x0F;
890 
891     VideoPortWritePortUchar(HwDeviceExtension->IOAddress + SEQ_DATA_PORT,
892             temp);
893 
894     VideoPortZeroDeviceMemory(HwDeviceExtension->VideoMemoryAddress, 0xFFFF);
895 
896     VgaInterpretCmdStream(HwDeviceExtension, DisableA000Color);
897 
898 }
899