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