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