2 Graphics Output Protocol functions for the QEMU video controller.
4 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
14 /// Generic Attribute Controller Register Settings
16 UINT8 AttributeController
[21] = {
17 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
18 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
19 0x41, 0x00, 0x0F, 0x00, 0x00
23 /// Generic Graphics Controller Register Settings
25 UINT8 GraphicsController
[9] = {
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF
30 // 640 x 480 x 256 color @ 60 Hertz
32 UINT8 Crtc_640_480_256_60
[28] = {
33 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
34 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
36 0xff, 0x00, 0x00, 0x22
39 UINT8 Crtc_640_480_32bpp_60
[28] = {
40 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,
41 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0xe1, 0x83, 0xdf, 0x40, 0x00, 0xe7, 0x04, 0xe3,
43 0xff, 0x00, 0x00, 0x32
46 UINT16 Seq_640_480_256_60
[15] = {
47 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
48 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
51 UINT16 Seq_640_480_32bpp_60
[15] = {
52 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
53 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e
57 // 800 x 600 x 256 color @ 60 Hertz
59 UINT8 Crtc_800_600_256_60
[28] = {
60 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
61 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
63 0xFF, 0x00, 0x00, 0x22
66 UINT8 Crtc_800_600_32bpp_60
[28] = {
67 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,
68 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x58, 0x8C, 0x57, 0x90, 0x00, 0x5F, 0x91, 0xE3,
70 0xFF, 0x00, 0x00, 0x32
73 UINT16 Seq_800_600_256_60
[15] = {
74 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
75 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
78 UINT16 Seq_800_600_32bpp_60
[15] = {
79 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
80 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e
83 UINT8 Crtc_960_720_32bpp_60
[28] = {
84 0xA3, 0x77, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
85 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0x02, 0x88, 0xCF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
87 0xFF, 0x4A, 0x00, 0x32
90 UINT16 Seq_960_720_32bpp_60
[15] = {
91 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
92 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
96 // 1024 x 768 x 256 color @ 60 Hertz
98 UINT8 Crtc_1024_768_256_60
[28] = {
99 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
100 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
102 0xFF, 0x4A, 0x00, 0x22
105 UINT16 Seq_1024_768_256_60
[15] = {
106 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,
107 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
111 // 1024 x 768 x 24-bit color @ 60 Hertz
113 UINT8 Crtc_1024_768_24bpp_60
[28] = {
114 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
115 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
117 0xFF, 0x4A, 0x00, 0x32
120 UINT16 Seq_1024_768_24bpp_60
[15] = {
121 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1507, 0x0008, 0x4a0b,
122 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
125 UINT8 Crtc_1024_768_32bpp_60
[28] = {
126 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,
127 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 0x02, 0x88, 0xFF, 0xe0, 0x00, 0x00, 0x64, 0xE3,
129 0xFF, 0x4A, 0x00, 0x32
132 UINT16 Seq_1024_768_32bpp_60
[15] = {
133 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,
134 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e
138 /// Table of supported video modes
140 QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes
[] = {
141 // { 640, 480, 8, Crtc_640_480_256_60, Seq_640_480_256_60, 0xe3 },
142 // { 800, 600, 8, Crtc_800_600_256_60, Seq_800_600_256_60, 0xef },
143 { 640, 480, 32, Crtc_640_480_32bpp_60
, Seq_640_480_32bpp_60
, 0xef },
144 { 800, 600, 32, Crtc_800_600_32bpp_60
, Seq_800_600_32bpp_60
, 0xef },
145 // { 1024, 768, 8, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }
146 { 1024, 768, 24, Crtc_1024_768_24bpp_60
, Seq_1024_768_24bpp_60
, 0xef }
147 // { 1024, 768, 32, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
148 // { 960, 720, 32, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef }
151 #define QEMU_VIDEO_CIRRUS_MODE_COUNT \
152 (ARRAY_SIZE (QemuVideoCirrusModes))
155 Construct the valid video modes for QemuVideo.
159 QemuVideoCirrusModeSetup (
160 QEMU_VIDEO_PRIVATE_DATA
*Private
164 QEMU_VIDEO_MODE_DATA
*ModeData
;
165 QEMU_VIDEO_CIRRUS_MODES
*VideoMode
;
170 Private
->ModeData
= AllocatePool (
171 sizeof (Private
->ModeData
[0]) * QEMU_VIDEO_CIRRUS_MODE_COUNT
173 if (Private
->ModeData
== NULL
) {
174 return EFI_OUT_OF_RESOURCES
;
176 ModeData
= Private
->ModeData
;
177 VideoMode
= &QemuVideoCirrusModes
[0];
178 for (Index
= 0; Index
< QEMU_VIDEO_CIRRUS_MODE_COUNT
; Index
++) {
179 ModeData
->InternalModeIndex
= Index
;
180 ModeData
->HorizontalResolution
= VideoMode
->Width
;
181 ModeData
->VerticalResolution
= VideoMode
->Height
;
182 ModeData
->ColorDepth
= VideoMode
->ColorDepth
;
184 "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit\n",
185 (INT32
) (ModeData
- Private
->ModeData
),
186 ModeData
->InternalModeIndex
,
187 ModeData
->HorizontalResolution
,
188 ModeData
->VerticalResolution
,
195 Private
->MaxMode
= ModeData
- Private
->ModeData
;
201 /// Table of supported video modes
203 QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes
[] = {
243 #define QEMU_VIDEO_BOCHS_MODE_COUNT \
244 (ARRAY_SIZE (QemuVideoBochsModes))
247 QemuVideoBochsModeSetup (
248 QEMU_VIDEO_PRIVATE_DATA
*Private
,
252 UINT32 AvailableFbSize
;
254 QEMU_VIDEO_MODE_DATA
*ModeData
;
255 QEMU_VIDEO_BOCHS_MODES
*VideoMode
;
258 // Fetch the available framebuffer size.
260 // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the
261 // drawable framebuffer. Up to and including qemu-2.1 however it used to
262 // return the size of PCI BAR 0 (ie. the full video RAM size).
264 // On stdvga the two concepts coincide with each other; the full memory size
265 // is usable for drawing.
267 // On QXL however, only a leading segment, "surface 0", can be used for
268 // drawing; the rest of the video memory is used for the QXL guest-host
269 // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of
270 // "surface 0", but since it doesn't (up to and including qemu-2.1), we
271 // retrieve the size of the drawable portion from a field in the QXL ROM BAR,
272 // where it is also available.
279 DrawStart
= 0xFFFFFFFF;
282 Private
->PciIo
->Mem
.Read (Private
->PciIo
, EfiPciIoWidthUint32
,
283 PCI_BAR_IDX2
, 0, 1, &Signature
)) ||
284 Signature
!= SIGNATURE_32 ('Q', 'X', 'R', 'O') ||
286 Private
->PciIo
->Mem
.Read (Private
->PciIo
, EfiPciIoWidthUint32
,
287 PCI_BAR_IDX2
, 36, 1, &DrawStart
)) ||
290 Private
->PciIo
->Mem
.Read (Private
->PciIo
, EfiPciIoWidthUint32
,
291 PCI_BAR_IDX2
, 40, 1, &AvailableFbSize
))) {
292 DEBUG ((EFI_D_ERROR
, "%a: can't read size of drawable buffer from QXL "
293 "ROM\n", __FUNCTION__
));
294 return EFI_NOT_FOUND
;
297 AvailableFbSize
= BochsRead (Private
, VBE_DISPI_INDEX_VIDEO_MEMORY_64K
);
298 AvailableFbSize
*= SIZE_64KB
;
300 DEBUG ((EFI_D_INFO
, "%a: AvailableFbSize=0x%x\n", __FUNCTION__
,
306 Private
->ModeData
= AllocatePool (
307 sizeof (Private
->ModeData
[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT
309 if (Private
->ModeData
== NULL
) {
310 return EFI_OUT_OF_RESOURCES
;
312 ModeData
= Private
->ModeData
;
313 VideoMode
= &QemuVideoBochsModes
[0];
314 for (Index
= 0; Index
< QEMU_VIDEO_BOCHS_MODE_COUNT
; Index
++) {
315 UINTN RequiredFbSize
;
317 ASSERT (VideoMode
->ColorDepth
% 8 == 0);
318 RequiredFbSize
= (UINTN
) VideoMode
->Width
* VideoMode
->Height
*
319 (VideoMode
->ColorDepth
/ 8);
320 if (RequiredFbSize
<= AvailableFbSize
) {
321 ModeData
->InternalModeIndex
= Index
;
322 ModeData
->HorizontalResolution
= VideoMode
->Width
;
323 ModeData
->VerticalResolution
= VideoMode
->Height
;
324 ModeData
->ColorDepth
= VideoMode
->ColorDepth
;
326 "Adding Mode %d as Bochs Internal Mode %d: %dx%d, %d-bit\n",
327 (INT32
) (ModeData
- Private
->ModeData
),
328 ModeData
->InternalModeIndex
,
329 ModeData
->HorizontalResolution
,
330 ModeData
->VerticalResolution
,
338 Private
->MaxMode
= ModeData
- Private
->ModeData
;