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