]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Initialize.c
OvmfPkg/QemuVideoDxe: rebase to ARRAY_SIZE()
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Initialize.c
CommitLineData
eaf4f336 1/** @file\r
2 Graphics Output Protocol functions for the QEMU video controller.\r
3\r
4 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "Qemu.h"\r
17\r
18\r
19///\r
20/// Generic Attribute Controller Register Settings\r
21///\r
22UINT8 AttributeController[21] = {\r
23 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\r
24 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,\r
25 0x41, 0x00, 0x0F, 0x00, 0x00\r
26};\r
27\r
28///\r
29/// Generic Graphics Controller Register Settings\r
30///\r
31UINT8 GraphicsController[9] = {\r
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF\r
33};\r
34\r
35//\r
36// 640 x 480 x 256 color @ 60 Hertz\r
37//\r
38UINT8 Crtc_640_480_256_60[28] = {\r
39 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,\r
40 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
41 0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,\r
42 0xff, 0x00, 0x00, 0x22\r
43};\r
44\r
45UINT8 Crtc_640_480_32bpp_60[28] = {\r
46 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e,\r
47 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
48 0xe1, 0x83, 0xdf, 0x40, 0x00, 0xe7, 0x04, 0xe3,\r
49 0xff, 0x00, 0x00, 0x32\r
50};\r
51\r
52UINT16 Seq_640_480_256_60[15] = {\r
53 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,\r
54 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e\r
55};\r
56\r
57UINT16 Seq_640_480_32bpp_60[15] = {\r
58 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
59 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e\r
60};\r
61\r
62//\r
63// 800 x 600 x 256 color @ 60 Hertz\r
64//\r
65UINT8 Crtc_800_600_256_60[28] = {\r
66 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,\r
67 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
68 0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,\r
69 0xFF, 0x00, 0x00, 0x22\r
70};\r
71\r
72UINT8 Crtc_800_600_32bpp_60[28] = {\r
73 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0,\r
74 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
75 0x58, 0x8C, 0x57, 0x90, 0x00, 0x5F, 0x91, 0xE3,\r
76 0xFF, 0x00, 0x00, 0x32\r
77};\r
78\r
79UINT16 Seq_800_600_256_60[15] = {\r
80 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,\r
81 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e\r
82};\r
83\r
84UINT16 Seq_800_600_32bpp_60[15] = {\r
85 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
86 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e\r
87};\r
88\r
89UINT8 Crtc_960_720_32bpp_60[28] = {\r
90 0xA3, 0x77, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
91 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
92 0x02, 0x88, 0xCF, 0xe0, 0x00, 0x00, 0x64, 0xE3,\r
93 0xFF, 0x4A, 0x00, 0x32\r
94};\r
95\r
96UINT16 Seq_960_720_32bpp_60[15] = {\r
97 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
98 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
99};\r
100\r
101//\r
102// 1024 x 768 x 256 color @ 60 Hertz\r
103//\r
104UINT8 Crtc_1024_768_256_60[28] = {\r
105 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
106 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
107 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,\r
108 0xFF, 0x4A, 0x00, 0x22\r
109};\r
110\r
111UINT16 Seq_1024_768_256_60[15] = {\r
112 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b,\r
113 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
114};\r
115\r
116//\r
117// 1024 x 768 x 24-bit color @ 60 Hertz\r
118//\r
119UINT8 Crtc_1024_768_24bpp_60[28] = {\r
120 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
121 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
122 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,\r
123 0xFF, 0x4A, 0x00, 0x32\r
124};\r
125\r
126UINT16 Seq_1024_768_24bpp_60[15] = {\r
127 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1507, 0x0008, 0x4a0b,\r
128 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
129};\r
130\r
131UINT8 Crtc_1024_768_32bpp_60[28] = {\r
132 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD,\r
133 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
134 0x02, 0x88, 0xFF, 0xe0, 0x00, 0x00, 0x64, 0xE3,\r
135 0xFF, 0x4A, 0x00, 0x32\r
136};\r
137\r
138UINT16 Seq_1024_768_32bpp_60[15] = {\r
139 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1907, 0x0008, 0x4a0b,\r
140 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e\r
141};\r
142\r
143///\r
144/// Table of supported video modes\r
145///\r
212aac55 146QEMU_VIDEO_CIRRUS_MODES QemuVideoCirrusModes[] = {\r
9ebb7ce8
LE
147// { 640, 480, 8, Crtc_640_480_256_60, Seq_640_480_256_60, 0xe3 },\r
148// { 800, 600, 8, Crtc_800_600_256_60, Seq_800_600_256_60, 0xef },\r
149 { 640, 480, 32, Crtc_640_480_32bpp_60, Seq_640_480_32bpp_60, 0xef },\r
150 { 800, 600, 32, Crtc_800_600_32bpp_60, Seq_800_600_32bpp_60, 0xef },\r
151// { 1024, 768, 8, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef }\r
152 { 1024, 768, 24, Crtc_1024_768_24bpp_60, Seq_1024_768_24bpp_60, 0xef }\r
153// { 1024, 768, 32, Crtc_1024_768_32bpp_60, Seq_1024_768_32bpp_60, 0xef }\r
154// { 960, 720, 32, Crtc_960_720_32bpp_60, Seq_1024_768_32bpp_60, 0xef }\r
eaf4f336 155};\r
156\r
212aac55 157#define QEMU_VIDEO_CIRRUS_MODE_COUNT \\r
b1bc305c 158 (ARRAY_SIZE (QemuVideoCirrusModes))\r
eaf4f336 159\r
160/**\r
161 Construct the valid video modes for QemuVideo.\r
162\r
163**/\r
164EFI_STATUS\r
212aac55 165QemuVideoCirrusModeSetup (\r
eaf4f336 166 QEMU_VIDEO_PRIVATE_DATA *Private\r
167 )\r
168{\r
169 UINT32 Index;\r
170 QEMU_VIDEO_MODE_DATA *ModeData;\r
212aac55 171 QEMU_VIDEO_CIRRUS_MODES *VideoMode;\r
eaf4f336 172\r
173 //\r
174 // Setup Video Modes\r
175 //\r
176 Private->ModeData = AllocatePool (\r
212aac55 177 sizeof (Private->ModeData[0]) * QEMU_VIDEO_CIRRUS_MODE_COUNT\r
eaf4f336 178 );\r
d89186bc
LE
179 if (Private->ModeData == NULL) {\r
180 return EFI_OUT_OF_RESOURCES;\r
181 }\r
eaf4f336 182 ModeData = Private->ModeData;\r
212aac55 183 VideoMode = &QemuVideoCirrusModes[0];\r
184 for (Index = 0; Index < QEMU_VIDEO_CIRRUS_MODE_COUNT; Index ++) {\r
cd152610 185 ModeData->InternalModeIndex = Index;\r
eaf4f336 186 ModeData->HorizontalResolution = VideoMode->Width;\r
187 ModeData->VerticalResolution = VideoMode->Height;\r
188 ModeData->ColorDepth = VideoMode->ColorDepth;\r
eaf4f336 189 DEBUG ((EFI_D_INFO,\r
0ccc97e9 190 "Adding Mode %d as Cirrus Internal Mode %d: %dx%d, %d-bit\n",\r
cd152610
LE
191 (INT32) (ModeData - Private->ModeData),\r
192 ModeData->InternalModeIndex,\r
eaf4f336 193 ModeData->HorizontalResolution,\r
194 ModeData->VerticalResolution,\r
0ccc97e9 195 ModeData->ColorDepth\r
eaf4f336 196 ));\r
197\r
198 ModeData ++ ;\r
199 VideoMode ++;\r
200 }\r
ec88061e 201 Private->MaxMode = ModeData - Private->ModeData;\r
eaf4f336 202\r
203 return EFI_SUCCESS;\r
204}\r
205\r
54f9b9ac 206///\r
207/// Table of supported video modes\r
208///\r
209QEMU_VIDEO_BOCHS_MODES QemuVideoBochsModes[] = {\r
bb97e788
LE
210 { 640, 480, 32 },\r
211 { 800, 480, 32 },\r
212 { 800, 600, 32 },\r
213 { 832, 624, 32 },\r
214 { 960, 640, 32 },\r
215 { 1024, 600, 32 },\r
216 { 1024, 768, 32 },\r
217 { 1152, 864, 32 },\r
218 { 1152, 870, 32 },\r
219 { 1280, 720, 32 },\r
220 { 1280, 760, 32 },\r
221 { 1280, 768, 32 },\r
222 { 1280, 800, 32 },\r
223 { 1280, 960, 32 },\r
224 { 1280, 1024, 32 },\r
225 { 1360, 768, 32 },\r
226 { 1366, 768, 32 },\r
227 { 1400, 1050, 32 },\r
228 { 1440, 900, 32 },\r
229 { 1600, 900, 32 },\r
230 { 1600, 1200, 32 },\r
231 { 1680, 1050, 32 },\r
232 { 1920, 1080, 32 },\r
233 { 1920, 1200, 32 },\r
234 { 1920, 1440, 32 },\r
235 { 2000, 2000, 32 },\r
236 { 2048, 1536, 32 },\r
237 { 2048, 2048, 32 },\r
238 { 2560, 1440, 32 },\r
239 { 2560, 1600, 32 },\r
240 { 2560, 2048, 32 },\r
241 { 2800, 2100, 32 },\r
242 { 3200, 2400, 32 },\r
243 { 3840, 2160, 32 },\r
244 { 4096, 2160, 32 },\r
245 { 7680, 4320, 32 },\r
246 { 8192, 4320, 32 }\r
54f9b9ac 247};\r
248\r
249#define QEMU_VIDEO_BOCHS_MODE_COUNT \\r
b1bc305c 250 (ARRAY_SIZE (QemuVideoBochsModes))\r
54f9b9ac 251\r
252EFI_STATUS\r
253QemuVideoBochsModeSetup (\r
b37bcfd6
LE
254 QEMU_VIDEO_PRIVATE_DATA *Private,\r
255 BOOLEAN IsQxl\r
54f9b9ac 256 )\r
257{\r
ec88061e 258 UINT32 AvailableFbSize;\r
54f9b9ac 259 UINT32 Index;\r
260 QEMU_VIDEO_MODE_DATA *ModeData;\r
261 QEMU_VIDEO_BOCHS_MODES *VideoMode;\r
262\r
ec88061e 263 //\r
b37bcfd6
LE
264 // Fetch the available framebuffer size.\r
265 //\r
266 // VBE_DISPI_INDEX_VIDEO_MEMORY_64K is expected to return the size of the\r
267 // drawable framebuffer. Up to and including qemu-2.1 however it used to\r
268 // return the size of PCI BAR 0 (ie. the full video RAM size).\r
269 //\r
270 // On stdvga the two concepts coincide with each other; the full memory size\r
271 // is usable for drawing.\r
ec88061e 272 //\r
b37bcfd6
LE
273 // On QXL however, only a leading segment, "surface 0", can be used for\r
274 // drawing; the rest of the video memory is used for the QXL guest-host\r
275 // protocol. VBE_DISPI_INDEX_VIDEO_MEMORY_64K should report the size of\r
276 // "surface 0", but since it doesn't (up to and including qemu-2.1), we\r
277 // retrieve the size of the drawable portion from a field in the QXL ROM BAR,\r
278 // where it is also available.\r
279 //\r
280 if (IsQxl) {\r
281 UINT32 Signature;\r
282 UINT32 DrawStart;\r
283\r
284 Signature = 0;\r
285 DrawStart = 0xFFFFFFFF;\r
286 AvailableFbSize = 0;\r
287 if (EFI_ERROR (\r
288 Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
289 PCI_BAR_IDX2, 0, 1, &Signature)) ||\r
290 Signature != SIGNATURE_32 ('Q', 'X', 'R', 'O') ||\r
291 EFI_ERROR (\r
292 Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
293 PCI_BAR_IDX2, 36, 1, &DrawStart)) ||\r
294 DrawStart != 0 ||\r
295 EFI_ERROR (\r
296 Private->PciIo->Mem.Read (Private->PciIo, EfiPciIoWidthUint32,\r
297 PCI_BAR_IDX2, 40, 1, &AvailableFbSize))) {\r
298 DEBUG ((EFI_D_ERROR, "%a: can't read size of drawable buffer from QXL "\r
299 "ROM\n", __FUNCTION__));\r
300 return EFI_NOT_FOUND;\r
301 }\r
302 } else {\r
303 AvailableFbSize = BochsRead (Private, VBE_DISPI_INDEX_VIDEO_MEMORY_64K);\r
304 AvailableFbSize *= SIZE_64KB;\r
305 }\r
4dd8787a 306 DEBUG ((EFI_D_INFO, "%a: AvailableFbSize=0x%x\n", __FUNCTION__,\r
ec88061e
LE
307 AvailableFbSize));\r
308\r
54f9b9ac 309 //\r
310 // Setup Video Modes\r
311 //\r
312 Private->ModeData = AllocatePool (\r
313 sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT\r
314 );\r
d89186bc
LE
315 if (Private->ModeData == NULL) {\r
316 return EFI_OUT_OF_RESOURCES;\r
317 }\r
54f9b9ac 318 ModeData = Private->ModeData;\r
319 VideoMode = &QemuVideoBochsModes[0];\r
320 for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) {\r
ec88061e
LE
321 UINTN RequiredFbSize;\r
322\r
323 ASSERT (VideoMode->ColorDepth % 8 == 0);\r
324 RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height *\r
325 (VideoMode->ColorDepth / 8);\r
326 if (RequiredFbSize <= AvailableFbSize) {\r
327 ModeData->InternalModeIndex = Index;\r
328 ModeData->HorizontalResolution = VideoMode->Width;\r
329 ModeData->VerticalResolution = VideoMode->Height;\r
330 ModeData->ColorDepth = VideoMode->ColorDepth;\r
ec88061e 331 DEBUG ((EFI_D_INFO,\r
0ccc97e9 332 "Adding Mode %d as Bochs Internal Mode %d: %dx%d, %d-bit\n",\r
ec88061e
LE
333 (INT32) (ModeData - Private->ModeData),\r
334 ModeData->InternalModeIndex,\r
335 ModeData->HorizontalResolution,\r
336 ModeData->VerticalResolution,\r
0ccc97e9 337 ModeData->ColorDepth\r
ec88061e
LE
338 ));\r
339\r
340 ModeData ++ ;\r
341 }\r
54f9b9ac 342 VideoMode ++;\r
343 }\r
ec88061e 344 Private->MaxMode = ModeData - Private->ModeData;\r
54f9b9ac 345\r
346 return EFI_SUCCESS;\r
347}\r
348\r