]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Driver.c
BaseTool: Fixed the incorrect cache key.
[mirror_edk2.git] / OvmfPkg / QemuVideoDxe / Driver.c
CommitLineData
eaf4f336 1/** @file\r
2 This driver is a sample implementation of the Graphics Output Protocol for\r
3 the QEMU (Cirrus Logic 5446) video controller.\r
4\r
5 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
6\r
7 This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
c137d950 17#include <IndustryStandard/VmwareSvga.h>\r
cdb4f5dc 18#include <IndustryStandard/Acpi.h>\r
c137d950
PDJ
19#include "Qemu.h"\r
20#include "UnalignedIoInternal.h"\r
eaf4f336 21\r
22EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {\r
23 QemuVideoControllerDriverSupported,\r
24 QemuVideoControllerDriverStart,\r
25 QemuVideoControllerDriverStop,\r
26 0x10,\r
27 NULL,\r
28 NULL\r
29};\r
30\r
212aac55 31QEMU_VIDEO_CARD gQemuVideoCardList[] = {\r
32 {\r
70dbd163 33 PCI_CLASS_DISPLAY_VGA,\r
212aac55 34 CIRRUS_LOGIC_VENDOR_ID,\r
35 CIRRUS_LOGIC_5430_DEVICE_ID,\r
36 QEMU_VIDEO_CIRRUS_5430,\r
37 L"Cirrus 5430"\r
38 },{\r
70dbd163 39 PCI_CLASS_DISPLAY_VGA,\r
212aac55 40 CIRRUS_LOGIC_VENDOR_ID,\r
41 CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,\r
42 QEMU_VIDEO_CIRRUS_5430,\r
43 L"Cirrus 5430"\r
44 },{\r
70dbd163 45 PCI_CLASS_DISPLAY_VGA,\r
212aac55 46 CIRRUS_LOGIC_VENDOR_ID,\r
47 CIRRUS_LOGIC_5446_DEVICE_ID,\r
48 QEMU_VIDEO_CIRRUS_5446,\r
49 L"Cirrus 5446"\r
54f9b9ac 50 },{\r
70dbd163 51 PCI_CLASS_DISPLAY_VGA,\r
54f9b9ac 52 0x1234,\r
53 0x1111,\r
cdb4f5dc 54 QEMU_VIDEO_BOCHS_MMIO,\r
54f9b9ac 55 L"QEMU Standard VGA"\r
333f32ec
GH
56 },{\r
57 PCI_CLASS_DISPLAY_OTHER,\r
58 0x1234,\r
59 0x1111,\r
60 QEMU_VIDEO_BOCHS_MMIO,\r
61 L"QEMU Standard VGA (secondary)"\r
54f9b9ac 62 },{\r
70dbd163 63 PCI_CLASS_DISPLAY_VGA,\r
54f9b9ac 64 0x1b36,\r
65 0x0100,\r
66 QEMU_VIDEO_BOCHS,\r
67 L"QEMU QXL VGA"\r
94210dc9 68 },{\r
70dbd163 69 PCI_CLASS_DISPLAY_VGA,\r
94210dc9
GH
70 0x1af4,\r
71 0x1050,\r
72 QEMU_VIDEO_BOCHS_MMIO,\r
73 L"QEMU VirtIO VGA"\r
c137d950 74 },{\r
70dbd163 75 PCI_CLASS_DISPLAY_VGA,\r
c137d950
PDJ
76 VMWARE_PCI_VENDOR_ID_VMWARE,\r
77 VMWARE_PCI_DEVICE_ID_VMWARE_SVGA2,\r
78 QEMU_VIDEO_VMWARE_SVGA,\r
79 L"QEMU VMWare SVGA"\r
212aac55 80 },{\r
81 0 /* end of list */\r
82 }\r
83};\r
84\r
85static QEMU_VIDEO_CARD*\r
86QemuVideoDetect(\r
70dbd163 87 IN UINT8 SubClass,\r
212aac55 88 IN UINT16 VendorId,\r
89 IN UINT16 DeviceId\r
90 )\r
91{\r
92 UINTN Index = 0;\r
93\r
94 while (gQemuVideoCardList[Index].VendorId != 0) {\r
70dbd163
GH
95 if (gQemuVideoCardList[Index].SubClass == SubClass &&\r
96 gQemuVideoCardList[Index].VendorId == VendorId &&\r
212aac55 97 gQemuVideoCardList[Index].DeviceId == DeviceId) {\r
98 return gQemuVideoCardList + Index;\r
99 }\r
100 Index++;\r
101 }\r
102 return NULL;\r
103}\r
104\r
eaf4f336 105/**\r
106 Check if this device is supported.\r
107\r
108 @param This The driver binding protocol.\r
109 @param Controller The controller handle to check.\r
110 @param RemainingDevicePath The remaining device path.\r
111\r
112 @retval EFI_SUCCESS The bus supports this controller.\r
113 @retval EFI_UNSUPPORTED This device isn't supported.\r
114\r
115**/\r
116EFI_STATUS\r
117EFIAPI\r
118QemuVideoControllerDriverSupported (\r
119 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
120 IN EFI_HANDLE Controller,\r
121 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
122 )\r
123{\r
124 EFI_STATUS Status;\r
125 EFI_PCI_IO_PROTOCOL *PciIo;\r
126 PCI_TYPE00 Pci;\r
212aac55 127 QEMU_VIDEO_CARD *Card;\r
eaf4f336 128\r
129 //\r
130 // Open the PCI I/O Protocol\r
131 //\r
132 Status = gBS->OpenProtocol (\r
133 Controller,\r
134 &gEfiPciIoProtocolGuid,\r
135 (VOID **) &PciIo,\r
136 This->DriverBindingHandle,\r
137 Controller,\r
138 EFI_OPEN_PROTOCOL_BY_DRIVER\r
139 );\r
140 if (EFI_ERROR (Status)) {\r
141 return Status;\r
142 }\r
143\r
144 //\r
145 // Read the PCI Configuration Header from the PCI Device\r
146 //\r
147 Status = PciIo->Pci.Read (\r
148 PciIo,\r
149 EfiPciIoWidthUint32,\r
150 0,\r
151 sizeof (Pci) / sizeof (UINT32),\r
152 &Pci\r
153 );\r
154 if (EFI_ERROR (Status)) {\r
155 goto Done;\r
156 }\r
157\r
158 Status = EFI_UNSUPPORTED;\r
70dbd163 159 if (!IS_PCI_DISPLAY (&Pci)) {\r
442c2ab8
LE
160 goto Done;\r
161 }\r
70dbd163 162 Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
212aac55 163 if (Card != NULL) {\r
164 DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));\r
165 Status = EFI_SUCCESS;\r
eaf4f336 166 }\r
167\r
168Done:\r
169 //\r
170 // Close the PCI I/O Protocol\r
171 //\r
172 gBS->CloseProtocol (\r
173 Controller,\r
174 &gEfiPciIoProtocolGuid,\r
175 This->DriverBindingHandle,\r
176 Controller\r
177 );\r
178\r
179 return Status;\r
180}\r
181\r
182/**\r
183 Start to process the controller.\r
184\r
185 @param This The USB bus driver binding instance.\r
186 @param Controller The controller to check.\r
187 @param RemainingDevicePath The remaining device patch.\r
188\r
189 @retval EFI_SUCCESS The controller is controlled by the usb bus.\r
190 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
191 bus.\r
192 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
193\r
194**/\r
195EFI_STATUS\r
196EFIAPI\r
197QemuVideoControllerDriverStart (\r
198 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
199 IN EFI_HANDLE Controller,\r
200 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
201 )\r
202{\r
9c08bbe5 203 EFI_TPL OldTpl;\r
cdb4f5dc 204 EFI_STATUS Status;\r
205 QEMU_VIDEO_PRIVATE_DATA *Private;\r
b37bcfd6 206 BOOLEAN IsQxl;\r
cdb4f5dc 207 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
42d0cad7 208 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
cdb4f5dc 209 PCI_TYPE00 Pci;\r
210 QEMU_VIDEO_CARD *Card;\r
4374c2e5 211 EFI_PCI_IO_PROTOCOL *ChildPciIo;\r
54f9b9ac 212\r
9c08bbe5
LE
213 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
214\r
eaf4f336 215 //\r
216 // Allocate Private context data for GOP inteface.\r
217 //\r
218 Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));\r
219 if (Private == NULL) {\r
9c08bbe5
LE
220 Status = EFI_OUT_OF_RESOURCES;\r
221 goto RestoreTpl;\r
eaf4f336 222 }\r
223\r
224 //\r
225 // Set up context record\r
226 //\r
227 Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;\r
eaf4f336 228\r
229 //\r
230 // Open PCI I/O Protocol\r
231 //\r
232 Status = gBS->OpenProtocol (\r
233 Controller,\r
234 &gEfiPciIoProtocolGuid,\r
235 (VOID **) &Private->PciIo,\r
236 This->DriverBindingHandle,\r
237 Controller,\r
238 EFI_OPEN_PROTOCOL_BY_DRIVER\r
239 );\r
240 if (EFI_ERROR (Status)) {\r
d89186bc 241 goto FreePrivate;\r
eaf4f336 242 }\r
243\r
212aac55 244 //\r
245 // Read the PCI Configuration Header from the PCI Device\r
246 //\r
247 Status = Private->PciIo->Pci.Read (\r
248 Private->PciIo,\r
249 EfiPciIoWidthUint32,\r
250 0,\r
251 sizeof (Pci) / sizeof (UINT32),\r
252 &Pci\r
253 );\r
254 if (EFI_ERROR (Status)) {\r
d89186bc 255 goto ClosePciIo;\r
212aac55 256 }\r
257\r
d89186bc
LE
258 //\r
259 // Determine card variant.\r
260 //\r
70dbd163 261 Card = QemuVideoDetect(Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
212aac55 262 if (Card == NULL) {\r
263 Status = EFI_DEVICE_ERROR;\r
d89186bc 264 goto ClosePciIo;\r
212aac55 265 }\r
266 Private->Variant = Card->Variant;\r
c137d950 267 Private->FrameBufferVramBarIndex = PCI_BAR_IDX0;\r
212aac55 268\r
b37bcfd6
LE
269 //\r
270 // IsQxl is based on the detected Card->Variant, which at a later point might\r
271 // not match Private->Variant.\r
272 //\r
273 IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS);\r
274\r
eaf4f336 275 //\r
276 // Save original PCI attributes\r
277 //\r
278 Status = Private->PciIo->Attributes (\r
279 Private->PciIo,\r
280 EfiPciIoAttributeOperationGet,\r
281 0,\r
282 &Private->OriginalPciAttributes\r
283 );\r
284\r
285 if (EFI_ERROR (Status)) {\r
d89186bc 286 goto ClosePciIo;\r
eaf4f336 287 }\r
eaf4f336 288\r
d89186bc
LE
289 //\r
290 // Set new PCI attributes\r
291 //\r
eaf4f336 292 Status = Private->PciIo->Attributes (\r
293 Private->PciIo,\r
294 EfiPciIoAttributeOperationEnable,\r
295 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,\r
296 NULL\r
297 );\r
298 if (EFI_ERROR (Status)) {\r
d89186bc 299 goto ClosePciIo;\r
eaf4f336 300 }\r
301\r
cdb4f5dc 302 //\r
303 // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+).\r
304 //\r
305 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
d89186bc
LE
306 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
307\r
cdb4f5dc 308 Status = Private->PciIo->GetBarAttributes (\r
309 Private->PciIo,\r
310 PCI_BAR_IDX2,\r
311 NULL,\r
312 (VOID**) &MmioDesc\r
313 );\r
314 if (EFI_ERROR (Status) ||\r
315 MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
316 DEBUG ((EFI_D_INFO, "QemuVideo: No mmio bar, fallback to port io\n"));\r
317 Private->Variant = QEMU_VIDEO_BOCHS;\r
318 } else {\r
319 DEBUG ((EFI_D_INFO, "QemuVideo: Using mmio bar @ 0x%lx\n",\r
320 MmioDesc->AddrRangeMin));\r
321 }\r
5cdb96fa
LE
322\r
323 if (!EFI_ERROR (Status)) {\r
324 FreePool (MmioDesc);\r
325 }\r
cdb4f5dc 326 }\r
327\r
54f9b9ac 328 //\r
329 // Check if accessing the bochs interface works.\r
330 //\r
cdb4f5dc 331 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
332 Private->Variant == QEMU_VIDEO_BOCHS) {\r
54f9b9ac 333 UINT16 BochsId;\r
334 BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);\r
335 if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {\r
336 DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));\r
337 Status = EFI_DEVICE_ERROR;\r
d89186bc 338 goto RestoreAttributes;\r
54f9b9ac 339 }\r
340 }\r
341\r
c137d950
PDJ
342 //\r
343 // Check if accessing Vmware SVGA interface works\r
344 //\r
345 if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) {\r
346 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *IoDesc;\r
347 UINT32 TargetId;\r
348 UINT32 SvgaIdRead;\r
349\r
350 IoDesc = NULL;\r
351 Status = Private->PciIo->GetBarAttributes (\r
352 Private->PciIo,\r
353 PCI_BAR_IDX0,\r
354 NULL,\r
355 (VOID**) &IoDesc\r
356 );\r
357 if (EFI_ERROR (Status) ||\r
358 IoDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_IO ||\r
359 IoDesc->AddrRangeMin > MAX_UINT16 + 1 - (VMWARE_SVGA_VALUE_PORT + 4)) {\r
360 if (IoDesc != NULL) {\r
361 FreePool (IoDesc);\r
362 }\r
363 Status = EFI_DEVICE_ERROR;\r
364 goto RestoreAttributes;\r
365 }\r
366 Private->VmwareSvgaBasePort = (UINT16) IoDesc->AddrRangeMin;\r
367 FreePool (IoDesc);\r
368\r
369 TargetId = VMWARE_SVGA_ID_2;\r
370 while (TRUE) {\r
371 VmwareSvgaWrite (Private, VmwareSvgaRegId, TargetId);\r
372 SvgaIdRead = VmwareSvgaRead (Private, VmwareSvgaRegId);\r
373 if ((SvgaIdRead == TargetId) || (TargetId <= VMWARE_SVGA_ID_0)) {\r
374 break;\r
375 }\r
376 TargetId--;\r
377 }\r
378\r
379 if (SvgaIdRead != TargetId) {\r
380 DEBUG ((\r
381 DEBUG_ERROR,\r
382 "QemuVideo: QEMU_VIDEO_VMWARE_SVGA ID mismatch "\r
383 "(got 0x%x, base address 0x%x)\n",\r
384 SvgaIdRead,\r
385 Private->VmwareSvgaBasePort\r
386 ));\r
387 Status = EFI_DEVICE_ERROR;\r
388 goto RestoreAttributes;\r
389 }\r
390\r
391 Private->FrameBufferVramBarIndex = PCI_BAR_IDX1;\r
392 }\r
393\r
eaf4f336 394 //\r
395 // Get ParentDevicePath\r
396 //\r
397 Status = gBS->HandleProtocol (\r
398 Controller,\r
399 &gEfiDevicePathProtocolGuid,\r
400 (VOID **) &ParentDevicePath\r
401 );\r
402 if (EFI_ERROR (Status)) {\r
d89186bc 403 goto RestoreAttributes;\r
eaf4f336 404 }\r
405\r
406 //\r
407 // Set Gop Device Path\r
408 //\r
42d0cad7
LE
409 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
410 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
411 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
412 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
413 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
414\r
415 Private->GopDevicePath = AppendDevicePathNode (\r
416 ParentDevicePath,\r
417 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
418 );\r
419 if (Private->GopDevicePath == NULL) {\r
420 Status = EFI_OUT_OF_RESOURCES;\r
421 goto RestoreAttributes;\r
eaf4f336 422 }\r
d89186bc
LE
423\r
424 //\r
42d0cad7 425 // Create new child handle and install the device path protocol on it.\r
d89186bc 426 //\r
42d0cad7
LE
427 Status = gBS->InstallMultipleProtocolInterfaces (\r
428 &Private->Handle,\r
429 &gEfiDevicePathProtocolGuid,\r
430 Private->GopDevicePath,\r
431 NULL\r
432 );\r
433 if (EFI_ERROR (Status)) {\r
434 goto FreeGopDevicePath;\r
eaf4f336 435 }\r
436\r
437 //\r
438 // Construct video mode buffer\r
439 //\r
212aac55 440 switch (Private->Variant) {\r
441 case QEMU_VIDEO_CIRRUS_5430:\r
442 case QEMU_VIDEO_CIRRUS_5446:\r
443 Status = QemuVideoCirrusModeSetup (Private);\r
444 break;\r
cdb4f5dc 445 case QEMU_VIDEO_BOCHS_MMIO:\r
54f9b9ac 446 case QEMU_VIDEO_BOCHS:\r
b37bcfd6 447 Status = QemuVideoBochsModeSetup (Private, IsQxl);\r
54f9b9ac 448 break;\r
c137d950
PDJ
449 case QEMU_VIDEO_VMWARE_SVGA:\r
450 Status = QemuVideoVmwareSvgaModeSetup (Private);\r
451 break;\r
212aac55 452 default:\r
453 ASSERT (FALSE);\r
454 Status = EFI_DEVICE_ERROR;\r
455 break;\r
456 }\r
eaf4f336 457 if (EFI_ERROR (Status)) {\r
d89186bc 458 goto UninstallGopDevicePath;\r
eaf4f336 459 }\r
460\r
d89186bc
LE
461 //\r
462 // Start the GOP software stack.\r
463 //\r
464 Status = QemuVideoGraphicsOutputConstructor (Private);\r
465 if (EFI_ERROR (Status)) {\r
466 goto FreeModeData;\r
467 }\r
4374c2e5 468\r
d89186bc
LE
469 Status = gBS->InstallMultipleProtocolInterfaces (\r
470 &Private->Handle,\r
471 &gEfiGraphicsOutputProtocolGuid,\r
472 &Private->GraphicsOutput,\r
473 NULL\r
4374c2e5 474 );\r
d89186bc
LE
475 if (EFI_ERROR (Status)) {\r
476 goto DestructQemuVideoGraphics;\r
eaf4f336 477 }\r
478\r
d89186bc
LE
479 //\r
480 // Reference parent handle from child handle.\r
481 //\r
482 Status = gBS->OpenProtocol (\r
483 Controller,\r
484 &gEfiPciIoProtocolGuid,\r
485 (VOID **) &ChildPciIo,\r
486 This->DriverBindingHandle,\r
487 Private->Handle,\r
488 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
489 );\r
eaf4f336 490 if (EFI_ERROR (Status)) {\r
d89186bc
LE
491 goto UninstallGop;\r
492 }\r
eaf4f336 493\r
84a75f70 494#if defined MDE_CPU_IA32 || defined MDE_CPU_X64\r
90803342
LE
495 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO ||\r
496 Private->Variant == QEMU_VIDEO_BOCHS) {\r
497 InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);\r
498 }\r
84a75f70 499#endif\r
90803342 500\r
9c08bbe5 501 gBS->RestoreTPL (OldTpl);\r
d89186bc
LE
502 return EFI_SUCCESS;\r
503\r
504UninstallGop:\r
505 gBS->UninstallProtocolInterface (Private->Handle,\r
506 &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput);\r
507\r
508DestructQemuVideoGraphics:\r
509 QemuVideoGraphicsOutputDestructor (Private);\r
510\r
511FreeModeData:\r
512 FreePool (Private->ModeData);\r
c137d950
PDJ
513 if (Private->VmwareSvgaModeInfo != NULL) {\r
514 FreePool (Private->VmwareSvgaModeInfo);\r
515 }\r
d89186bc
LE
516\r
517UninstallGopDevicePath:\r
d89186bc
LE
518 gBS->UninstallProtocolInterface (Private->Handle,\r
519 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
520\r
521FreeGopDevicePath:\r
42d0cad7 522 FreePool (Private->GopDevicePath);\r
eaf4f336 523\r
d89186bc
LE
524RestoreAttributes:\r
525 Private->PciIo->Attributes (Private->PciIo, EfiPciIoAttributeOperationSet,\r
526 Private->OriginalPciAttributes, NULL);\r
527\r
528ClosePciIo:\r
529 gBS->CloseProtocol (Controller, &gEfiPciIoProtocolGuid,\r
530 This->DriverBindingHandle, Controller);\r
531\r
532FreePrivate:\r
533 FreePool (Private);\r
534\r
9c08bbe5
LE
535RestoreTpl:\r
536 gBS->RestoreTPL (OldTpl);\r
537\r
eaf4f336 538 return Status;\r
539}\r
540\r
541/**\r
542 Stop this device\r
543\r
544 @param This The USB bus driver binding protocol.\r
545 @param Controller The controller to release.\r
546 @param NumberOfChildren The number of children of this device that\r
547 opened the controller BY_CHILD.\r
548 @param ChildHandleBuffer The array of child handle.\r
549\r
550 @retval EFI_SUCCESS The controller or children are stopped.\r
551 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
552\r
553**/\r
554EFI_STATUS\r
555EFIAPI\r
556QemuVideoControllerDriverStop (\r
557 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
558 IN EFI_HANDLE Controller,\r
559 IN UINTN NumberOfChildren,\r
560 IN EFI_HANDLE *ChildHandleBuffer\r
561 )\r
562{\r
563 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
564\r
565 EFI_STATUS Status;\r
566 QEMU_VIDEO_PRIVATE_DATA *Private;\r
567\r
99a6dce3
LE
568 if (NumberOfChildren == 0) {\r
569 //\r
570 // Close the PCI I/O Protocol\r
571 //\r
572 gBS->CloseProtocol (\r
573 Controller,\r
574 &gEfiPciIoProtocolGuid,\r
575 This->DriverBindingHandle,\r
576 Controller\r
577 );\r
578 return EFI_SUCCESS;\r
579 }\r
580\r
581 //\r
582 // free all resources for whose access we need the child handle, because the\r
583 // child handle is going away\r
584 //\r
585 ASSERT (NumberOfChildren == 1);\r
eaf4f336 586 Status = gBS->OpenProtocol (\r
99a6dce3 587 ChildHandleBuffer[0],\r
eaf4f336 588 &gEfiGraphicsOutputProtocolGuid,\r
589 (VOID **) &GraphicsOutput,\r
590 This->DriverBindingHandle,\r
591 Controller,\r
592 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
593 );\r
594 if (EFI_ERROR (Status)) {\r
595 return Status;\r
596 }\r
597\r
598 //\r
599 // Get our private context information\r
600 //\r
601 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
99a6dce3 602 ASSERT (Private->Handle == ChildHandleBuffer[0]);\r
eaf4f336 603\r
604 QemuVideoGraphicsOutputDestructor (Private);\r
605 //\r
606 // Remove the GOP protocol interface from the system\r
607 //\r
608 Status = gBS->UninstallMultipleProtocolInterfaces (\r
609 Private->Handle,\r
610 &gEfiGraphicsOutputProtocolGuid,\r
611 &Private->GraphicsOutput,\r
612 NULL\r
613 );\r
614\r
615 if (EFI_ERROR (Status)) {\r
616 return Status;\r
617 }\r
618\r
619 //\r
620 // Restore original PCI attributes\r
621 //\r
622 Private->PciIo->Attributes (\r
623 Private->PciIo,\r
624 EfiPciIoAttributeOperationSet,\r
625 Private->OriginalPciAttributes,\r
626 NULL\r
627 );\r
628\r
4374c2e5
CR
629 gBS->CloseProtocol (\r
630 Controller,\r
631 &gEfiPciIoProtocolGuid,\r
632 This->DriverBindingHandle,\r
633 Private->Handle\r
634 );\r
635\r
847e4c34 636 FreePool (Private->ModeData);\r
c137d950
PDJ
637 if (Private->VmwareSvgaModeInfo != NULL) {\r
638 FreePool (Private->VmwareSvgaModeInfo);\r
639 }\r
847e4c34
LE
640 gBS->UninstallProtocolInterface (Private->Handle,\r
641 &gEfiDevicePathProtocolGuid, Private->GopDevicePath);\r
642 FreePool (Private->GopDevicePath);\r
643\r
eaf4f336 644 //\r
645 // Free our instance data\r
646 //\r
647 gBS->FreePool (Private);\r
648\r
649 return EFI_SUCCESS;\r
650}\r
651\r
652/**\r
653 TODO: Add function description\r
654\r
655 @param Private TODO: add argument description\r
656 @param Address TODO: add argument description\r
657 @param Data TODO: add argument description\r
658\r
659 TODO: add return values\r
660\r
661**/\r
662VOID\r
663outb (\r
664 QEMU_VIDEO_PRIVATE_DATA *Private,\r
665 UINTN Address,\r
666 UINT8 Data\r
667 )\r
668{\r
669 Private->PciIo->Io.Write (\r
670 Private->PciIo,\r
671 EfiPciIoWidthUint8,\r
672 EFI_PCI_IO_PASS_THROUGH_BAR,\r
673 Address,\r
674 1,\r
675 &Data\r
676 );\r
677}\r
678\r
679/**\r
680 TODO: Add function description\r
681\r
682 @param Private TODO: add argument description\r
683 @param Address TODO: add argument description\r
684 @param Data TODO: add argument description\r
685\r
686 TODO: add return values\r
687\r
688**/\r
689VOID\r
690outw (\r
691 QEMU_VIDEO_PRIVATE_DATA *Private,\r
692 UINTN Address,\r
693 UINT16 Data\r
694 )\r
695{\r
696 Private->PciIo->Io.Write (\r
697 Private->PciIo,\r
698 EfiPciIoWidthUint16,\r
699 EFI_PCI_IO_PASS_THROUGH_BAR,\r
700 Address,\r
701 1,\r
702 &Data\r
703 );\r
704}\r
705\r
706/**\r
707 TODO: Add function description\r
708\r
709 @param Private TODO: add argument description\r
710 @param Address TODO: add argument description\r
711\r
712 TODO: add return values\r
713\r
714**/\r
715UINT8\r
716inb (\r
717 QEMU_VIDEO_PRIVATE_DATA *Private,\r
718 UINTN Address\r
719 )\r
720{\r
721 UINT8 Data;\r
722\r
723 Private->PciIo->Io.Read (\r
724 Private->PciIo,\r
725 EfiPciIoWidthUint8,\r
726 EFI_PCI_IO_PASS_THROUGH_BAR,\r
727 Address,\r
728 1,\r
729 &Data\r
730 );\r
731 return Data;\r
732}\r
733\r
734/**\r
735 TODO: Add function description\r
736\r
737 @param Private TODO: add argument description\r
738 @param Address TODO: add argument description\r
739\r
740 TODO: add return values\r
741\r
742**/\r
743UINT16\r
744inw (\r
745 QEMU_VIDEO_PRIVATE_DATA *Private,\r
746 UINTN Address\r
747 )\r
748{\r
749 UINT16 Data;\r
750\r
751 Private->PciIo->Io.Read (\r
752 Private->PciIo,\r
753 EfiPciIoWidthUint16,\r
754 EFI_PCI_IO_PASS_THROUGH_BAR,\r
755 Address,\r
756 1,\r
757 &Data\r
758 );\r
759 return Data;\r
760}\r
761\r
762/**\r
763 TODO: Add function description\r
764\r
765 @param Private TODO: add argument description\r
766 @param Index TODO: add argument description\r
767 @param Red TODO: add argument description\r
768 @param Green TODO: add argument description\r
769 @param Blue TODO: add argument description\r
770\r
771 TODO: add return values\r
772\r
773**/\r
774VOID\r
775SetPaletteColor (\r
776 QEMU_VIDEO_PRIVATE_DATA *Private,\r
777 UINTN Index,\r
778 UINT8 Red,\r
779 UINT8 Green,\r
780 UINT8 Blue\r
781 )\r
782{\r
cdb4f5dc 783 VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);\r
784 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));\r
785 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));\r
786 VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));\r
eaf4f336 787}\r
788\r
789/**\r
790 TODO: Add function description\r
791\r
792 @param Private TODO: add argument description\r
793\r
794 TODO: add return values\r
795\r
796**/\r
797VOID\r
798SetDefaultPalette (\r
799 QEMU_VIDEO_PRIVATE_DATA *Private\r
800 )\r
801{\r
802 UINTN Index;\r
803 UINTN RedIndex;\r
804 UINTN GreenIndex;\r
805 UINTN BlueIndex;\r
806\r
807 Index = 0;\r
808 for (RedIndex = 0; RedIndex < 8; RedIndex++) {\r
809 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {\r
810 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {\r
811 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));\r
812 Index++;\r
813 }\r
814 }\r
815 }\r
816}\r
817\r
818/**\r
819 TODO: Add function description\r
820\r
821 @param Private TODO: add argument description\r
822\r
823 TODO: add return values\r
824\r
825**/\r
826VOID\r
827ClearScreen (\r
828 QEMU_VIDEO_PRIVATE_DATA *Private\r
829 )\r
830{\r
831 UINT32 Color;\r
832\r
833 Color = 0;\r
834 Private->PciIo->Mem.Write (\r
835 Private->PciIo,\r
836 EfiPciIoWidthFillUint32,\r
c137d950 837 Private->FrameBufferVramBarIndex,\r
eaf4f336 838 0,\r
839 0x400000 >> 2,\r
840 &Color\r
841 );\r
842}\r
843\r
844/**\r
845 TODO: Add function description\r
846\r
847 @param Private TODO: add argument description\r
848\r
849 TODO: add return values\r
850\r
851**/\r
852VOID\r
853DrawLogo (\r
854 QEMU_VIDEO_PRIVATE_DATA *Private,\r
855 UINTN ScreenWidth,\r
856 UINTN ScreenHeight\r
857 )\r
858{\r
859}\r
860\r
861/**\r
862 TODO: Add function description\r
863\r
864 @param Private TODO: add argument description\r
865 @param ModeData TODO: add argument description\r
866\r
867 TODO: add return values\r
868\r
869**/\r
870VOID\r
212aac55 871InitializeCirrusGraphicsMode (\r
eaf4f336 872 QEMU_VIDEO_PRIVATE_DATA *Private,\r
212aac55 873 QEMU_VIDEO_CIRRUS_MODES *ModeData\r
eaf4f336 874 )\r
875{\r
876 UINT8 Byte;\r
877 UINTN Index;\r
eaf4f336 878\r
879 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);\r
880 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);\r
881\r
882 for (Index = 0; Index < 15; Index++) {\r
883 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);\r
884 }\r
885\r
212aac55 886 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {\r
eaf4f336 887 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);\r
888 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);\r
889 outb (Private, SEQ_DATA_REGISTER, Byte);\r
890 }\r
891\r
892 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);\r
893 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);\r
894 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);\r
895 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);\r
896\r
897 for (Index = 0; Index < 28; Index++) {\r
898 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));\r
899 }\r
900\r
901 for (Index = 0; Index < 9; Index++) {\r
902 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));\r
903 }\r
904\r
905 inb (Private, INPUT_STATUS_1_REGISTER);\r
906\r
907 for (Index = 0; Index < 21; Index++) {\r
908 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);\r
909 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);\r
910 }\r
911\r
912 outb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
913\r
914 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);\r
915 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);\r
916 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);\r
917 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);\r
918\r
54f9b9ac 919 SetDefaultPalette (Private);\r
920 ClearScreen (Private);\r
921}\r
922\r
923VOID\r
924BochsWrite (\r
925 QEMU_VIDEO_PRIVATE_DATA *Private,\r
926 UINT16 Reg,\r
927 UINT16 Data\r
928 )\r
929{\r
cdb4f5dc 930 EFI_STATUS Status;\r
931\r
932 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
933 Status = Private->PciIo->Mem.Write (\r
934 Private->PciIo,\r
935 EfiPciIoWidthUint16,\r
936 PCI_BAR_IDX2,\r
937 0x500 + (Reg << 1),\r
938 1,\r
939 &Data\r
940 );\r
941 ASSERT_EFI_ERROR (Status);\r
942 } else {\r
943 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
944 outw (Private, VBE_DISPI_IOPORT_DATA, Data);\r
945 }\r
54f9b9ac 946}\r
947\r
948UINT16\r
949BochsRead (\r
950 QEMU_VIDEO_PRIVATE_DATA *Private,\r
951 UINT16 Reg\r
952 )\r
953{\r
cdb4f5dc 954 EFI_STATUS Status;\r
955 UINT16 Data;\r
956\r
957 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
958 Status = Private->PciIo->Mem.Read (\r
959 Private->PciIo,\r
960 EfiPciIoWidthUint16,\r
961 PCI_BAR_IDX2,\r
962 0x500 + (Reg << 1),\r
963 1,\r
964 &Data\r
965 );\r
966 ASSERT_EFI_ERROR (Status);\r
967 } else {\r
968 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
969 Data = inw (Private, VBE_DISPI_IOPORT_DATA);\r
970 }\r
54f9b9ac 971 return Data;\r
972}\r
973\r
c137d950
PDJ
974VOID\r
975VmwareSvgaWrite (\r
976 QEMU_VIDEO_PRIVATE_DATA *Private,\r
977 UINT16 Register,\r
978 UINT32 Value\r
979 )\r
980{\r
981 UnalignedIoWrite32 (\r
982 Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,\r
983 Register\r
984 );\r
985 UnalignedIoWrite32 (\r
986 Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT,\r
987 Value\r
988 );\r
989}\r
990\r
991UINT32\r
992VmwareSvgaRead (\r
993 QEMU_VIDEO_PRIVATE_DATA *Private,\r
994 UINT16 Register\r
995 )\r
996{\r
997 UnalignedIoWrite32 (\r
998 Private->VmwareSvgaBasePort + VMWARE_SVGA_INDEX_PORT,\r
999 Register\r
1000 );\r
1001 return UnalignedIoRead32 (\r
1002 Private->VmwareSvgaBasePort + VMWARE_SVGA_VALUE_PORT\r
1003 );\r
1004}\r
1005\r
cdb4f5dc 1006VOID\r
1007VgaOutb (\r
1008 QEMU_VIDEO_PRIVATE_DATA *Private,\r
1009 UINTN Reg,\r
1010 UINT8 Data\r
1011 )\r
1012{\r
1013 EFI_STATUS Status;\r
1014\r
1015 if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) {\r
1016 Status = Private->PciIo->Mem.Write (\r
1017 Private->PciIo,\r
1018 EfiPciIoWidthUint8,\r
1019 PCI_BAR_IDX2,\r
1020 0x400 - 0x3c0 + Reg,\r
1021 1,\r
1022 &Data\r
1023 );\r
1024 ASSERT_EFI_ERROR (Status);\r
1025 } else {\r
1026 outb (Private, Reg, Data);\r
1027 }\r
1028}\r
1029\r
54f9b9ac 1030VOID\r
1031InitializeBochsGraphicsMode (\r
1032 QEMU_VIDEO_PRIVATE_DATA *Private,\r
1033 QEMU_VIDEO_BOCHS_MODES *ModeData\r
1034 )\r
1035{\r
1036 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",\r
1037 ModeData->Width, ModeData->Height, ModeData->ColorDepth));\r
1038\r
1039 /* unblank */\r
cdb4f5dc 1040 VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
54f9b9ac 1041\r
1042 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);\r
1043 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);\r
1044 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);\r
1045 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);\r
1046\r
1047 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);\r
1048 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);\r
1049 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);\r
1050 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);\r
1051 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);\r
1052\r
1053 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,\r
1054 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);\r
1055\r
c137d950
PDJ
1056 SetDefaultPalette (Private);\r
1057 ClearScreen (Private);\r
1058}\r
1059\r
1060VOID\r
1061InitializeVmwareSvgaGraphicsMode (\r
1062 QEMU_VIDEO_PRIVATE_DATA *Private,\r
1063 QEMU_VIDEO_BOCHS_MODES *ModeData\r
1064 )\r
1065{\r
1066 UINT32 Capabilities;\r
1067\r
1068 VmwareSvgaWrite (Private, VmwareSvgaRegWidth, ModeData->Width);\r
1069 VmwareSvgaWrite (Private, VmwareSvgaRegHeight, ModeData->Height);\r
1070\r
1071 Capabilities = VmwareSvgaRead (\r
1072 Private,\r
1073 VmwareSvgaRegCapabilities\r
1074 );\r
1075 if ((Capabilities & VMWARE_SVGA_CAP_8BIT_EMULATION) != 0) {\r
1076 VmwareSvgaWrite (\r
1077 Private,\r
1078 VmwareSvgaRegBitsPerPixel,\r
1079 ModeData->ColorDepth\r
1080 );\r
1081 }\r
1082\r
1083 VmwareSvgaWrite (Private, VmwareSvgaRegEnable, 1);\r
1084\r
eaf4f336 1085 SetDefaultPalette (Private);\r
1086 ClearScreen (Private);\r
1087}\r
1088\r
1089EFI_STATUS\r
1090EFIAPI\r
1091InitializeQemuVideo (\r
1092 IN EFI_HANDLE ImageHandle,\r
1093 IN EFI_SYSTEM_TABLE *SystemTable\r
1094 )\r
1095{\r
1096 EFI_STATUS Status;\r
1097\r
1098 Status = EfiLibInstallDriverBindingComponentName2 (\r
1099 ImageHandle,\r
1100 SystemTable,\r
1101 &gQemuVideoDriverBinding,\r
1102 ImageHandle,\r
1103 &gQemuVideoComponentName,\r
1104 &gQemuVideoComponentName2\r
1105 );\r
1106 ASSERT_EFI_ERROR (Status);\r
1107\r
1108 //\r
1109 // Install EFI Driver Supported EFI Version Protocol required for\r
1110 // EFI drivers that are on PCI and other plug in cards.\r
1111 //\r
1112 gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);\r
1113 Status = gBS->InstallMultipleProtocolInterfaces (\r
1114 &ImageHandle,\r
1115 &gEfiDriverSupportedEfiVersionProtocolGuid,\r
1116 &gQemuVideoDriverSupportedEfiVersion,\r
1117 NULL\r
1118 );\r
1119 ASSERT_EFI_ERROR (Status);\r
1120\r
1121 return Status;\r
1122}\r