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