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