2 * PROJECT: ReactOS VGA Miniport Driver
3 * LICENSE: Microsoft NT4 DDK Sample Code License
4 * FILE: boot/drivers/video/miniport/vga/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
13 VgaInterpretCmdStream(
14 PHW_DEVICE_EXTENSION HwDeviceExtension
,
20 PHW_DEVICE_EXTENSION HwDeviceExtension
,
23 // eVb: 2.1 [SET MODE] - Add new output parameter for framebuffer update functionality
29 VgaQueryAvailableModes(
30 PHW_DEVICE_EXTENSION HwDeviceExtension
,
31 PVIDEO_MODE_INFORMATION ModeInformation
,
32 ULONG ModeInformationSize
,
37 VgaQueryNumberOfAvailableModes(
38 PHW_DEVICE_EXTENSION HwDeviceExtension
,
39 PVIDEO_NUM_MODES NumModes
,
46 PHW_DEVICE_EXTENSION HwDeviceExtension
49 #if defined(ALLOC_PRAGMA)
50 #pragma alloc_text(PAGE,VgaInterpretCmdStream)
51 #pragma alloc_text(PAGE,VgaSetMode)
52 #pragma alloc_text(PAGE,VgaQueryAvailableModes)
53 #pragma alloc_text(PAGE,VgaQueryNumberOfAvailableModes)
54 #pragma alloc_text(PAGE,VgaZeroVideoMemory)
57 //---------------------------------------------------------------------------
59 VgaInterpretCmdStream(
60 PHW_DEVICE_EXTENSION HwDeviceExtension
,
68 Interprets the appropriate command array to set up VGA registers for the
69 requested mode. Typically used to set the VGA into a particular mode by
70 programming all of the registers
74 HwDeviceExtension - Pointer to the miniport driver's device extension.
76 pusCmdStream - array of commands to be interpreted.
80 The status of the operation (can only fail on a bad command); TRUE for
81 success, FALSE for failure.
94 if (pusCmdStream
== NULL
) {
96 VideoDebugPrint((1, "VgaInterpretCmdStream - Invalid pusCmdStream\n"));
100 ulBase
= (ULONG
)HwDeviceExtension
->IOAddress
;
103 // Now set the adapter to the desired mode.
106 while ((ulCmd
= *pusCmdStream
++) != EOD
) {
109 // Determine major command type
112 switch (ulCmd
& 0xF0) {
115 // Basic input/output command
121 // Determine type of inout instruction
127 // Out instruction. Single or multiple outs?
130 if (!(ulCmd
& MULTI
)) {
133 // Single out. Byte or word out?
142 ulPort
= *pusCmdStream
++;
143 jValue
= (UCHAR
) *pusCmdStream
++;
144 VideoPortWritePortUchar((PUCHAR
)(ulBase
+ulPort
),
153 ulPort
= *pusCmdStream
++;
154 usValue
= *pusCmdStream
++;
155 VideoPortWritePortUshort((PUSHORT
)(ulBase
+ulPort
),
163 // Output a string of values
164 // Byte or word outs?
170 // String byte outs. Do in a loop; can't use
171 // VideoPortWritePortBufferUchar because the data
175 ulPort
= ulBase
+ *pusCmdStream
++;
176 culCount
= *pusCmdStream
++;
179 jValue
= (UCHAR
) *pusCmdStream
++;
180 VideoPortWritePortUchar((PUCHAR
)ulPort
,
191 ulPort
= *pusCmdStream
++;
192 culCount
= *pusCmdStream
++;
193 VideoPortWritePortBufferUshort((PUSHORT
)
194 (ulBase
+ ulPort
), pusCmdStream
, culCount
);
195 pusCmdStream
+= culCount
;
204 // Currently, string in instructions aren't supported; all
205 // in instructions are handled as single-byte ins
215 ulPort
= *pusCmdStream
++;
216 jValue
= VideoPortReadPortUchar((PUCHAR
)ulBase
+ulPort
);
224 ulPort
= *pusCmdStream
++;
225 usValue
= VideoPortReadPortUshort((PUSHORT
)
235 // Higher-level input/output commands
241 // Determine type of metaout command, based on minor
244 switch (ulCmd
& 0x0F) {
252 ulPort
= ulBase
+ *pusCmdStream
++;
253 culCount
= *pusCmdStream
++;
254 ulIndex
= *pusCmdStream
++;
258 usValue
= (USHORT
) (ulIndex
+
259 (((ULONG
)(*pusCmdStream
++)) << 8));
260 VideoPortWritePortUshort((PUSHORT
)ulPort
, usValue
);
269 // Masked out (read, AND, XOR, write)
274 ulPort
= *pusCmdStream
++;
275 jValue
= VideoPortReadPortUchar((PUCHAR
)ulBase
+ulPort
);
276 jValue
&= *pusCmdStream
++;
277 jValue
^= *pusCmdStream
++;
278 VideoPortWritePortUchar((PUCHAR
)ulBase
+ ulPort
,
283 // Attribute Controller out
288 ulPort
= ulBase
+ *pusCmdStream
++;
289 culCount
= *pusCmdStream
++;
290 ulIndex
= *pusCmdStream
++;
294 // Write Attribute Controller index
295 VideoPortWritePortUchar((PUCHAR
)ulPort
,
298 // Write Attribute Controller data
299 jValue
= (UCHAR
) *pusCmdStream
++;
300 VideoPortWritePortUchar((PUCHAR
)ulPort
, jValue
);
309 // None of the above; error
329 // Unknown command; error
342 } // end VgaInterpretCmdStream()
347 PHW_DEVICE_EXTENSION HwDeviceExtension
,
350 // eVb: 2.2 [SET MODE] - Add new output parameter for framebuffer update functionality
359 This routine sets the vga into the requested mode.
363 HwDeviceExtension - Pointer to the miniport driver's device extension.
365 Mode - Pointer to the structure containing the information about the
368 ModeSize - Length of the input buffer supplied by the user.
372 ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough
375 ERROR_INVALID_PARAMETER if the mode number is invalid.
377 NO_ERROR if the operation completed successfully.
382 PVIDEOMODE pRequestedMode
;
384 ULONG RequestedModeNum
;
385 // eVb: 2.3 [SET MODE] - Add new output parameter for framebuffer update functionality
386 *PhysPtrChange
= FALSE
;
389 // Check if the size of the data in the input buffer is large enough.
392 if (ModeSize
< sizeof(VIDEO_MODE
))
394 return ERROR_INSUFFICIENT_BUFFER
;
398 // Extract the clear memory, and map linear bits.
401 RequestedModeNum
= Mode
->RequestedMode
&
402 ~(VIDEO_MODE_NO_ZERO_MEMORY
| VIDEO_MODE_MAP_MEM_LINEAR
);
405 if (!(Mode
->RequestedMode
& VIDEO_MODE_NO_ZERO_MEMORY
))
408 VgaZeroVideoMemory(HwDeviceExtension
);
413 // Check to see if we are requesting a valid mode
415 // eVb: 2.4 [CIRRUS] - Remove Cirrus-specific check for valid mode
416 if ( (RequestedModeNum
>= NumVideoModes
) )
419 VideoDebugPrint((0, "Invalide Mode Number = %d!\n", RequestedModeNum
));
421 return ERROR_INVALID_PARAMETER
;
424 VideoDebugPrint((2, "Attempting to set mode %d\n",
426 // eVb: 2.5 [VBE] - Use dynamic VBE mode list instead of hard-coded VGA list
427 pRequestedMode
= &VgaModeList
[RequestedModeNum
];
429 VideoDebugPrint((2, "Info on Requested Mode:\n"
430 "\tResolution: %dx%d\n",
431 pRequestedMode
->hres
,
432 pRequestedMode
->vres
));
435 // VESA BIOS mode switch
437 // eVb: 2.6 [VBE] - VBE Mode Switch Support
438 status
= VbeSetMode(HwDeviceExtension
, pRequestedMode
, PhysPtrChange
);
439 if (status
== ERROR_INVALID_FUNCTION
)
445 if (!pRequestedMode
->CmdStream
) return ERROR_INVALID_FUNCTION
;
446 if (!VgaInterpretCmdStream(HwDeviceExtension
, pRequestedMode
->CmdStream
)) return ERROR_INVALID_FUNCTION
;
449 else if (status
!= NO_ERROR
) return status
;
451 // eVb: 2.7 [MODE-X] - Windows VGA Miniport Supports Mode-X, we should too
456 if (pRequestedMode
->hres
== 320)
458 VideoPortDebugPrint(0, "ModeX not support!!!\n");
459 return ERROR_INVALID_PARAMETER
;
466 if (!(pRequestedMode
->fbType
& VIDEO_MODE_GRAPHICS
))
468 // eVb: 2.8 [TODO] - This code path is not implemented yet
469 VideoPortDebugPrint(0, "Text-mode not support!!!\n");
470 return ERROR_INVALID_PARAMETER
;
476 // Update the location of the physical frame buffer within video memory.
478 // eVb: 2.9 [VBE] - Linear and banked support is unified in VGA, unlike Cirrus
479 HwDeviceExtension
->PhysicalVideoMemoryBase
.LowPart
= pRequestedMode
->PhysBase
;
480 HwDeviceExtension
->PhysicalVideoMemoryLength
= pRequestedMode
->PhysSize
;
482 HwDeviceExtension
->PhysicalFrameLength
=
483 pRequestedMode
->FrameBufferSize
;
485 HwDeviceExtension
->PhysicalFrameOffset
.LowPart
=
486 pRequestedMode
->FrameBufferBase
;
490 // Store the new mode value.
493 HwDeviceExtension
->CurrentMode
= pRequestedMode
;
494 HwDeviceExtension
->ModeIndex
= Mode
->RequestedMode
;
501 VgaQueryAvailableModes(
502 PHW_DEVICE_EXTENSION HwDeviceExtension
,
503 PVIDEO_MODE_INFORMATION ModeInformation
,
504 ULONG ModeInformationSize
,
512 This routine returns the list of all available available modes on the
517 HwDeviceExtension - Pointer to the miniport driver's device extension.
519 ModeInformation - Pointer to the output buffer supplied by the user.
520 This is where the list of all valid modes is stored.
522 ModeInformationSize - Length of the output buffer supplied by the user.
524 OutputSize - Pointer to a buffer in which to return the actual size of
525 the data in the buffer. If the buffer was not large enough, this
526 contains the minimum required buffer size.
530 ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
531 for the data being returned.
533 NO_ERROR if the operation completed successfully.
538 PVIDEO_MODE_INFORMATION videoModes
= ModeInformation
;
542 // Find out the size of the data to be put in the buffer and return
543 // that in the status information (whether or not the information is
544 // there). If the buffer passed in is not large enough return an
545 // appropriate error code.
548 if (ModeInformationSize
< (*OutputSize
=
549 // eVb: 2.10 [VBE] - We store VBE/VGA mode count in this global, not in DevExt like Cirrus
552 sizeof(VIDEO_MODE_INFORMATION
)) ) {
554 return ERROR_INSUFFICIENT_BUFFER
;
559 // For each mode supported by the card, store the mode characteristics
560 // in the output buffer.
563 for (i
= 0; i
< NumVideoModes
; i
++)
565 videoModes
->Length
= sizeof(VIDEO_MODE_INFORMATION
);
566 videoModes
->ModeIndex
= i
;
567 // eVb: 2.11 [VBE] - Use dynamic VBE mode list instead of hard-coded VGA list
568 videoModes
->VisScreenWidth
= VgaModeList
[i
].hres
;
569 videoModes
->ScreenStride
= VgaModeList
[i
].wbytes
;
570 videoModes
->VisScreenHeight
= VgaModeList
[i
].vres
;
571 videoModes
->NumberOfPlanes
= VgaModeList
[i
].numPlanes
;
572 videoModes
->BitsPerPlane
= VgaModeList
[i
].bitsPerPlane
;
573 videoModes
->Frequency
= VgaModeList
[i
].Frequency
;
574 videoModes
->XMillimeter
= 320; // temporary hardcoded constant
575 videoModes
->YMillimeter
= 240; // temporary hardcoded constant
576 videoModes
->AttributeFlags
= VgaModeList
[i
].fbType
;
579 if ((VgaModeList
[i
].bitsPerPlane
== 32) ||
580 (VgaModeList
[i
].bitsPerPlane
== 24))
583 videoModes
->NumberRedBits
= 8;
584 videoModes
->NumberGreenBits
= 8;
585 videoModes
->NumberBlueBits
= 8;
586 videoModes
->RedMask
= 0xff0000;
587 videoModes
->GreenMask
= 0x00ff00;
588 videoModes
->BlueMask
= 0x0000ff;
591 else if (VgaModeList
[i
].bitsPerPlane
== 16)
594 videoModes
->NumberRedBits
= 6;
595 videoModes
->NumberGreenBits
= 6;
596 videoModes
->NumberBlueBits
= 6;
597 videoModes
->RedMask
= 0x1F << 11;
598 videoModes
->GreenMask
= 0x3F << 5;
599 videoModes
->BlueMask
= 0x1F;
602 // eVb: 2.12 [VGA] - Add support for 15bpp modes, which Cirrus doesn't support
603 else if (VgaModeList
[i
].bitsPerPlane
== 15)
606 videoModes
->NumberRedBits
= 6;
607 videoModes
->NumberGreenBits
= 6;
608 videoModes
->NumberBlueBits
= 6;
609 videoModes
->RedMask
= 0x3E << 9;
610 videoModes
->GreenMask
= 0x1F << 5;
611 videoModes
->BlueMask
= 0x1F;
617 videoModes
->NumberRedBits
= 6;
618 videoModes
->NumberGreenBits
= 6;
619 videoModes
->NumberBlueBits
= 6;
620 videoModes
->RedMask
= 0;
621 videoModes
->GreenMask
= 0;
622 videoModes
->BlueMask
= 0;
625 // eVb: 2.13 [VGA] - All modes are palette managed/driven, unlike Cirrus
626 videoModes
->AttributeFlags
|= VIDEO_MODE_PALETTE_DRIVEN
|
627 VIDEO_MODE_MANAGED_PALETTE
;
635 } // end VgaGetAvailableModes()
638 VgaQueryNumberOfAvailableModes(
639 PHW_DEVICE_EXTENSION HwDeviceExtension
,
640 PVIDEO_NUM_MODES NumModes
,
649 This routine returns the number of available modes for this particular
654 HwDeviceExtension - Pointer to the miniport driver's device extension.
656 NumModes - Pointer to the output buffer supplied by the user. This is
657 where the number of modes is stored.
659 NumModesSize - Length of the output buffer supplied by the user.
661 OutputSize - Pointer to a buffer in which to return the actual size of
662 the data in the buffer.
666 ERROR_INSUFFICIENT_BUFFER if the output buffer was not large enough
667 for the data being returned.
669 NO_ERROR if the operation completed successfully.
675 // Find out the size of the data to be put in the the buffer and return
676 // that in the status information (whether or not the information is
677 // there). If the buffer passed in is not large enough return an
678 // appropriate error code.
681 if (NumModesSize
< (*OutputSize
= sizeof(VIDEO_NUM_MODES
)) ) {
683 return ERROR_INSUFFICIENT_BUFFER
;
688 // Store the number of modes into the buffer.
691 // eVb: 2.14 [VBE] - We store VBE/VGA mode count in this global, not in DevExt like Cirrus
692 NumModes
->NumModes
= NumVideoModes
;
694 NumModes
->ModeInformationLength
= sizeof(VIDEO_MODE_INFORMATION
);
698 } // end VgaGetNumberOfAvailableModes()
702 PHW_DEVICE_EXTENSION HwDeviceExtension
709 This routine zeros the first 256K on the VGA.
713 HwDeviceExtension - Pointer to the miniport driver's device extension.
725 // Map font buffer at A0000
728 VgaInterpretCmdStream(HwDeviceExtension
, EnableA000Data
);
731 // Enable all planes.
734 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ SEQ_ADDRESS_PORT
,
737 temp
= VideoPortReadPortUchar(HwDeviceExtension
->IOAddress
+
738 SEQ_DATA_PORT
) | (UCHAR
)0x0F;
740 VideoPortWritePortUchar(HwDeviceExtension
->IOAddress
+ SEQ_DATA_PORT
,
743 VideoPortZeroDeviceMemory(HwDeviceExtension
->VideoMemoryAddress
, 0xFFFF);
745 VgaInterpretCmdStream(HwDeviceExtension
, DisableA000Color
);