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