]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Gop.c
QemuVideo: prepare to support more hardware
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Gop.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#include <IndustryStandard/Acpi.h>\r
18#include <Library/BltLib.h>\r
19\r
20STATIC\r
21VOID\r
22QemuVideoCompleteModeInfo (\r
23 IN QEMU_VIDEO_MODE_DATA *ModeData,\r
24 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info\r
25 )\r
26{\r
27 Info->Version = 0;\r
28 if (ModeData->ColorDepth == 8) {\r
29 Info->PixelFormat = PixelBitMask;\r
30 Info->PixelInformation.RedMask = PIXEL_RED_MASK;\r
31 Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;\r
32 Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;\r
33 Info->PixelInformation.ReservedMask = 0;\r
34 } else if (ModeData->ColorDepth == 24) {\r
35 Info->PixelFormat = PixelBitMask;\r
36 Info->PixelInformation.RedMask = PIXEL24_RED_MASK;\r
37 Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;\r
38 Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;\r
39 Info->PixelInformation.ReservedMask = 0;\r
40 } else if (ModeData->ColorDepth == 32) {\r
41 DEBUG ((EFI_D_INFO, "PixelBlueGreenRedReserved8BitPerColor\n"));\r
42 Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;\r
43 }\r
44 Info->PixelsPerScanLine = Info->HorizontalResolution;\r
45}\r
46\r
47\r
48STATIC\r
49EFI_STATUS\r
50QemuVideoCompleteModeData (\r
51 IN QEMU_VIDEO_PRIVATE_DATA *Private,\r
52 OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode\r
53 )\r
54{\r
55 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
56 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc;\r
57 QEMU_VIDEO_MODE_DATA *ModeData;\r
58\r
59 ModeData = &Private->ModeData[Mode->Mode];\r
60 Info = Mode->Info;\r
61 QemuVideoCompleteModeInfo (ModeData, Info);\r
62\r
63 Private->PciIo->GetBarAttributes (\r
64 Private->PciIo,\r
65 0,\r
66 NULL,\r
67 (VOID**) &FrameBufDesc\r
68 );\r
69\r
70 Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin;\r
71 Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution;\r
72 Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8);\r
73 DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", Mode->FrameBufferBase, Mode->FrameBufferSize));\r
74\r
75 return EFI_SUCCESS;\r
76}\r
77\r
78\r
79//\r
80// Graphics Output Protocol Member Functions\r
81//\r
82EFI_STATUS\r
83EFIAPI\r
84QemuVideoGraphicsOutputQueryMode (\r
85 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
86 IN UINT32 ModeNumber,\r
87 OUT UINTN *SizeOfInfo,\r
88 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info\r
89 )\r
90/*++\r
91\r
92Routine Description:\r
93\r
94 Graphics Output protocol interface to query video mode\r
95\r
96 Arguments:\r
97 This - Protocol instance pointer.\r
98 ModeNumber - The mode number to return information on.\r
99 Info - Caller allocated buffer that returns information about ModeNumber.\r
100 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.\r
101\r
102 Returns:\r
103 EFI_SUCCESS - Mode information returned.\r
104 EFI_BUFFER_TOO_SMALL - The Info buffer was too small.\r
105 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.\r
106 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()\r
107 EFI_INVALID_PARAMETER - One of the input args was NULL.\r
108\r
109--*/\r
110{\r
111 QEMU_VIDEO_PRIVATE_DATA *Private;\r
112 QEMU_VIDEO_MODE_DATA *ModeData;\r
113\r
114 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
115\r
116 if (Private->HardwareNeedsStarting) {\r
117 return EFI_NOT_STARTED;\r
118 }\r
119\r
120 if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {\r
121 return EFI_INVALID_PARAMETER;\r
122 }\r
123\r
124 *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));\r
125 if (*Info == NULL) {\r
126 return EFI_OUT_OF_RESOURCES;\r
127 }\r
128\r
129 *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
130\r
131 ModeData = &Private->ModeData[ModeNumber];\r
132 (*Info)->HorizontalResolution = ModeData->HorizontalResolution;\r
133 (*Info)->VerticalResolution = ModeData->VerticalResolution;\r
134 QemuVideoCompleteModeInfo (ModeData, *Info);\r
135\r
136 return EFI_SUCCESS;\r
137}\r
138\r
139EFI_STATUS\r
140EFIAPI\r
141QemuVideoGraphicsOutputSetMode (\r
142 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
143 IN UINT32 ModeNumber\r
144 )\r
145/*++\r
146\r
147Routine Description:\r
148\r
149 Graphics Output protocol interface to set video mode\r
150\r
151 Arguments:\r
152 This - Protocol instance pointer.\r
153 ModeNumber - The mode number to be set.\r
154\r
155 Returns:\r
156 EFI_SUCCESS - Graphics mode was changed.\r
157 EFI_DEVICE_ERROR - The device had an error and could not complete the request.\r
158 EFI_UNSUPPORTED - ModeNumber is not supported by this device.\r
159\r
160--*/\r
161{\r
162 QEMU_VIDEO_PRIVATE_DATA *Private;\r
163 QEMU_VIDEO_MODE_DATA *ModeData;\r
164// UINTN Count;\r
165\r
166 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This);\r
167\r
168 if (ModeNumber >= This->Mode->MaxMode) {\r
169 return EFI_UNSUPPORTED;\r
170 }\r
171\r
172 ModeData = &Private->ModeData[ModeNumber];\r
173\r
174 if (Private->LineBuffer) {\r
175 gBS->FreePool (Private->LineBuffer);\r
176 }\r
177\r
178 Private->LineBuffer = NULL;\r
179 Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution);\r
180 if (Private->LineBuffer == NULL) {\r
181 return EFI_OUT_OF_RESOURCES;\r
182 }\r
183\r
212aac55 184 switch (Private->Variant) {\r
185 case QEMU_VIDEO_CIRRUS_5430:\r
186 case QEMU_VIDEO_CIRRUS_5446:\r
187 InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->ModeNumber]);\r
188 break;\r
189 default:\r
190 ASSERT (FALSE);\r
191 gBS->FreePool (Private->LineBuffer);\r
192 Private->LineBuffer = NULL;\r
193 return EFI_DEVICE_ERROR;\r
194 }\r
eaf4f336 195\r
196 This->Mode->Mode = ModeNumber;\r
197 This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;\r
198 This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;\r
199 This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);\r
200\r
201 QemuVideoCompleteModeData (Private, This->Mode);\r
202\r
203 BltLibConfigure (\r
204 (VOID*)(UINTN) This->Mode->FrameBufferBase,\r
205 This->Mode->Info\r
206 );\r
207\r
208 Private->HardwareNeedsStarting = FALSE;\r
209\r
210 return EFI_SUCCESS;\r
211}\r
212\r
213EFI_STATUS\r
214EFIAPI\r
215QemuVideoGraphicsOutputBlt (\r
216 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,\r
217 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL\r
218 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,\r
219 IN UINTN SourceX,\r
220 IN UINTN SourceY,\r
221 IN UINTN DestinationX,\r
222 IN UINTN DestinationY,\r
223 IN UINTN Width,\r
224 IN UINTN Height,\r
225 IN UINTN Delta\r
226 )\r
227/*++\r
228\r
229Routine Description:\r
230\r
231 Graphics Output protocol instance to block transfer for CirrusLogic device\r
232\r
233Arguments:\r
234\r
235 This - Pointer to Graphics Output protocol instance\r
236 BltBuffer - The data to transfer to screen\r
237 BltOperation - The operation to perform\r
238 SourceX - The X coordinate of the source for BltOperation\r
239 SourceY - The Y coordinate of the source for BltOperation\r
240 DestinationX - The X coordinate of the destination for BltOperation\r
241 DestinationY - The Y coordinate of the destination for BltOperation\r
242 Width - The width of a rectangle in the blt rectangle in pixels\r
243 Height - The height of a rectangle in the blt rectangle in pixels\r
244 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.\r
245 If a Delta of 0 is used, the entire BltBuffer will be operated on.\r
246 If a subrectangle of the BltBuffer is used, then Delta represents\r
247 the number of bytes in a row of the BltBuffer.\r
248\r
249Returns:\r
250\r
251 EFI_INVALID_PARAMETER - Invalid parameter passed in\r
252 EFI_SUCCESS - Blt operation success\r
253\r
254--*/\r
255{\r
256 EFI_STATUS Status;\r
257 EFI_TPL OriginalTPL;\r
258\r
259 //\r
260 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.\r
261 // We would not want a timer based event (Cursor, ...) to come in while we are\r
262 // doing this operation.\r
263 //\r
264 OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);\r
265\r
266 switch (BltOperation) {\r
267 case EfiBltVideoToBltBuffer:\r
268 case EfiBltBufferToVideo:\r
269 case EfiBltVideoFill:\r
270 case EfiBltVideoToVideo:\r
271 Status = BltLibGopBlt (\r
272 BltBuffer,\r
273 BltOperation,\r
274 SourceX,\r
275 SourceY,\r
276 DestinationX,\r
277 DestinationY,\r
278 Width,\r
279 Height,\r
280 Delta\r
281 );\r
282 break;\r
283\r
284 default:\r
285 Status = EFI_INVALID_PARAMETER;\r
286 ASSERT (FALSE);\r
287 }\r
288\r
289 gBS->RestoreTPL (OriginalTPL);\r
290\r
291 return Status;\r
292}\r
293\r
294EFI_STATUS\r
295QemuVideoGraphicsOutputConstructor (\r
296 QEMU_VIDEO_PRIVATE_DATA *Private\r
297 )\r
298{\r
299 EFI_STATUS Status;\r
300 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
301\r
302\r
303 GraphicsOutput = &Private->GraphicsOutput;\r
304 GraphicsOutput->QueryMode = QemuVideoGraphicsOutputQueryMode;\r
305 GraphicsOutput->SetMode = QemuVideoGraphicsOutputSetMode;\r
306 GraphicsOutput->Blt = QemuVideoGraphicsOutputBlt;\r
307\r
308 //\r
309 // Initialize the private data\r
310 //\r
311 Status = gBS->AllocatePool (\r
312 EfiBootServicesData,\r
313 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE),\r
314 (VOID **) &Private->GraphicsOutput.Mode\r
315 );\r
316 if (EFI_ERROR (Status)) {\r
317 return Status;\r
318 }\r
319 Status = gBS->AllocatePool (\r
320 EfiBootServicesData,\r
321 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),\r
322 (VOID **) &Private->GraphicsOutput.Mode->Info\r
323 );\r
324 if (EFI_ERROR (Status)) {\r
325 return Status;\r
326 }\r
327 Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode;\r
328 Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER;\r
329 Private->HardwareNeedsStarting = TRUE;\r
330 Private->LineBuffer = NULL;\r
331\r
332 //\r
333 // Initialize the hardware\r
334 //\r
335 GraphicsOutput->SetMode (GraphicsOutput, 0);\r
336 DrawLogo (\r
337 Private,\r
338 Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution,\r
339 Private->ModeData[Private->GraphicsOutput.Mode->Mode].VerticalResolution\r
340 );\r
341\r
342 return EFI_SUCCESS;\r
343}\r
344\r
345EFI_STATUS\r
346QemuVideoGraphicsOutputDestructor (\r
347 QEMU_VIDEO_PRIVATE_DATA *Private\r
348 )\r
349/*++\r
350\r
351Routine Description:\r
352\r
353Arguments:\r
354\r
355Returns:\r
356\r
357 None\r
358\r
359--*/\r
360{\r
361 if (Private->GraphicsOutput.Mode != NULL) {\r
362 if (Private->GraphicsOutput.Mode->Info != NULL) {\r
363 gBS->FreePool (Private->GraphicsOutput.Mode->Info);\r
364 }\r
365 gBS->FreePool (Private->GraphicsOutput.Mode);\r
366 }\r
367\r
368 return EFI_SUCCESS;\r
369}\r
370\r
371\r