]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuVideoDxe/Driver.c
QemuVideo: Add support for the bochs dispi interface
[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
18\r
19EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = {\r
20 QemuVideoControllerDriverSupported,\r
21 QemuVideoControllerDriverStart,\r
22 QemuVideoControllerDriverStop,\r
23 0x10,\r
24 NULL,\r
25 NULL\r
26};\r
27\r
212aac55 28QEMU_VIDEO_CARD gQemuVideoCardList[] = {\r
29 {\r
30 CIRRUS_LOGIC_VENDOR_ID,\r
31 CIRRUS_LOGIC_5430_DEVICE_ID,\r
32 QEMU_VIDEO_CIRRUS_5430,\r
33 L"Cirrus 5430"\r
34 },{\r
35 CIRRUS_LOGIC_VENDOR_ID,\r
36 CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID,\r
37 QEMU_VIDEO_CIRRUS_5430,\r
38 L"Cirrus 5430"\r
39 },{\r
40 CIRRUS_LOGIC_VENDOR_ID,\r
41 CIRRUS_LOGIC_5446_DEVICE_ID,\r
42 QEMU_VIDEO_CIRRUS_5446,\r
43 L"Cirrus 5446"\r
54f9b9ac 44 },{\r
45 0x1234,\r
46 0x1111,\r
47 QEMU_VIDEO_BOCHS,\r
48 L"QEMU Standard VGA"\r
49 },{\r
50 0x1b36,\r
51 0x0100,\r
52 QEMU_VIDEO_BOCHS,\r
53 L"QEMU QXL VGA"\r
212aac55 54 },{\r
55 0 /* end of list */\r
56 }\r
57};\r
58\r
59static QEMU_VIDEO_CARD*\r
60QemuVideoDetect(\r
61 IN UINT16 VendorId,\r
62 IN UINT16 DeviceId\r
63 )\r
64{\r
65 UINTN Index = 0;\r
66\r
67 while (gQemuVideoCardList[Index].VendorId != 0) {\r
68 if (gQemuVideoCardList[Index].VendorId == VendorId &&\r
69 gQemuVideoCardList[Index].DeviceId == DeviceId) {\r
70 return gQemuVideoCardList + Index;\r
71 }\r
72 Index++;\r
73 }\r
74 return NULL;\r
75}\r
76\r
eaf4f336 77/**\r
78 Check if this device is supported.\r
79\r
80 @param This The driver binding protocol.\r
81 @param Controller The controller handle to check.\r
82 @param RemainingDevicePath The remaining device path.\r
83\r
84 @retval EFI_SUCCESS The bus supports this controller.\r
85 @retval EFI_UNSUPPORTED This device isn't supported.\r
86\r
87**/\r
88EFI_STATUS\r
89EFIAPI\r
90QemuVideoControllerDriverSupported (\r
91 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
92 IN EFI_HANDLE Controller,\r
93 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
94 )\r
95{\r
96 EFI_STATUS Status;\r
97 EFI_PCI_IO_PROTOCOL *PciIo;\r
98 PCI_TYPE00 Pci;\r
99 EFI_DEV_PATH *Node;\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
132 //\r
133 // See if the I/O enable is on. Most systems only allow one VGA device to be turned on\r
134 // at a time, so see if this is one that is turned on.\r
135 //\r
136 // if (((Pci.Hdr.Command & 0x01) == 0x01)) {\r
137 //\r
138 // See if this is a Cirrus Logic PCI controller\r
139 //\r
212aac55 140 Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
141 if (Card != NULL) {\r
142 DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name));\r
143 Status = EFI_SUCCESS;\r
eaf4f336 144 //\r
212aac55 145 // If this is an Intel 945 graphics controller,\r
146 // go further check RemainingDevicePath validation\r
eaf4f336 147 //\r
212aac55 148 if (RemainingDevicePath != NULL) {\r
149 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
eaf4f336 150 //\r
212aac55 151 // Check if RemainingDevicePath is the End of Device Path Node, \r
152 // if yes, return EFI_SUCCESS\r
eaf4f336 153 //\r
212aac55 154 if (!IsDevicePathEnd (Node)) {\r
eaf4f336 155 //\r
212aac55 156 // If RemainingDevicePath isn't the End of Device Path Node,\r
157 // check its validation\r
eaf4f336 158 //\r
212aac55 159 if (Node->DevPath.Type != ACPI_DEVICE_PATH ||\r
160 Node->DevPath.SubType != ACPI_ADR_DP ||\r
161 DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) {\r
162 Status = EFI_UNSUPPORTED;\r
eaf4f336 163 }\r
164 }\r
165 }\r
166 }\r
167\r
168Done:\r
169 //\r
170 // Close the PCI I/O Protocol\r
171 //\r
172 gBS->CloseProtocol (\r
173 Controller,\r
174 &gEfiPciIoProtocolGuid,\r
175 This->DriverBindingHandle,\r
176 Controller\r
177 );\r
178\r
179 return Status;\r
180}\r
181\r
182/**\r
183 Start to process the controller.\r
184\r
185 @param This The USB bus driver binding instance.\r
186 @param Controller The controller to check.\r
187 @param RemainingDevicePath The remaining device patch.\r
188\r
189 @retval EFI_SUCCESS The controller is controlled by the usb bus.\r
190 @retval EFI_ALREADY_STARTED The controller is already controlled by the usb\r
191 bus.\r
192 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
193\r
194**/\r
195EFI_STATUS\r
196EFIAPI\r
197QemuVideoControllerDriverStart (\r
198 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
199 IN EFI_HANDLE Controller,\r
200 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
201 )\r
202{\r
203 EFI_STATUS Status;\r
204 QEMU_VIDEO_PRIVATE_DATA *Private;\r
205 BOOLEAN PciAttributesSaved;\r
206 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
207 ACPI_ADR_DEVICE_PATH AcpiDeviceNode;\r
212aac55 208 PCI_TYPE00 Pci;\r
209 QEMU_VIDEO_CARD *Card;\r
54f9b9ac 210\r
eaf4f336 211 PciAttributesSaved = FALSE;\r
212 //\r
213 // Allocate Private context data for GOP inteface.\r
214 //\r
215 Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA));\r
216 if (Private == NULL) {\r
217 Status = EFI_OUT_OF_RESOURCES;\r
218 goto Error;\r
219 }\r
220\r
221 //\r
222 // Set up context record\r
223 //\r
224 Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE;\r
225 Private->Handle = NULL;\r
226\r
227 //\r
228 // Open PCI I/O Protocol\r
229 //\r
230 Status = gBS->OpenProtocol (\r
231 Controller,\r
232 &gEfiPciIoProtocolGuid,\r
233 (VOID **) &Private->PciIo,\r
234 This->DriverBindingHandle,\r
235 Controller,\r
236 EFI_OPEN_PROTOCOL_BY_DRIVER\r
237 );\r
238 if (EFI_ERROR (Status)) {\r
239 goto Error;\r
240 }\r
241\r
212aac55 242 //\r
243 // Read the PCI Configuration Header from the PCI Device\r
244 //\r
245 Status = Private->PciIo->Pci.Read (\r
246 Private->PciIo,\r
247 EfiPciIoWidthUint32,\r
248 0,\r
249 sizeof (Pci) / sizeof (UINT32),\r
250 &Pci\r
251 );\r
252 if (EFI_ERROR (Status)) {\r
253 goto Error;\r
254 }\r
255\r
256 Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId);\r
257 if (Card == NULL) {\r
258 Status = EFI_DEVICE_ERROR;\r
259 goto Error;\r
260 }\r
261 Private->Variant = Card->Variant;\r
262\r
eaf4f336 263 //\r
264 // Save original PCI attributes\r
265 //\r
266 Status = Private->PciIo->Attributes (\r
267 Private->PciIo,\r
268 EfiPciIoAttributeOperationGet,\r
269 0,\r
270 &Private->OriginalPciAttributes\r
271 );\r
272\r
273 if (EFI_ERROR (Status)) {\r
274 goto Error;\r
275 }\r
276 PciAttributesSaved = TRUE;\r
277\r
278 Status = Private->PciIo->Attributes (\r
279 Private->PciIo,\r
280 EfiPciIoAttributeOperationEnable,\r
281 EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO,\r
282 NULL\r
283 );\r
284 if (EFI_ERROR (Status)) {\r
285 goto Error;\r
286 }\r
287\r
54f9b9ac 288 //\r
289 // Check if accessing the bochs interface works.\r
290 //\r
291 if (Private->Variant == QEMU_VIDEO_BOCHS) {\r
292 UINT16 BochsId;\r
293 BochsId = BochsRead(Private, VBE_DISPI_INDEX_ID);\r
294 if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) {\r
295 DEBUG ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId));\r
296 Status = EFI_DEVICE_ERROR;\r
297 goto Error;\r
298 }\r
299 }\r
300\r
eaf4f336 301 //\r
302 // Get ParentDevicePath\r
303 //\r
304 Status = gBS->HandleProtocol (\r
305 Controller,\r
306 &gEfiDevicePathProtocolGuid,\r
307 (VOID **) &ParentDevicePath\r
308 );\r
309 if (EFI_ERROR (Status)) {\r
310 goto Error;\r
311 }\r
312\r
313 //\r
314 // Set Gop Device Path\r
315 //\r
316 if (RemainingDevicePath == NULL) {\r
317 ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH));\r
318 AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH;\r
319 AcpiDeviceNode.Header.SubType = ACPI_ADR_DP;\r
320 AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0);\r
321 SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
322\r
323 Private->GopDevicePath = AppendDevicePathNode (\r
324 ParentDevicePath,\r
325 (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode\r
326 );\r
327 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
328 //\r
329 // If RemainingDevicePath isn't the End of Device Path Node, \r
330 // only scan the specified device by RemainingDevicePath\r
331 //\r
332 Private->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath);\r
333 } else {\r
334 //\r
335 // If RemainingDevicePath is the End of Device Path Node, \r
336 // don't create child device and return EFI_SUCCESS\r
337 //\r
338 Private->GopDevicePath = NULL;\r
339 }\r
340 \r
341 if (Private->GopDevicePath != NULL) {\r
342 //\r
343 // Creat child handle and device path protocol firstly\r
344 //\r
345 Private->Handle = NULL;\r
346 Status = gBS->InstallMultipleProtocolInterfaces (\r
347 &Private->Handle,\r
348 &gEfiDevicePathProtocolGuid,\r
349 Private->GopDevicePath,\r
350 NULL\r
351 );\r
352 }\r
353\r
354 //\r
355 // Construct video mode buffer\r
356 //\r
212aac55 357 switch (Private->Variant) {\r
358 case QEMU_VIDEO_CIRRUS_5430:\r
359 case QEMU_VIDEO_CIRRUS_5446:\r
360 Status = QemuVideoCirrusModeSetup (Private);\r
361 break;\r
54f9b9ac 362 case QEMU_VIDEO_BOCHS:\r
363 Status = QemuVideoBochsModeSetup (Private);\r
364 break;\r
212aac55 365 default:\r
366 ASSERT (FALSE);\r
367 Status = EFI_DEVICE_ERROR;\r
368 break;\r
369 }\r
eaf4f336 370 if (EFI_ERROR (Status)) {\r
371 goto Error;\r
372 }\r
373\r
374 if (Private->GopDevicePath == NULL) {\r
375 //\r
376 // If RemainingDevicePath is the End of Device Path Node, \r
377 // don't create child device and return EFI_SUCCESS\r
378 //\r
379 Status = EFI_SUCCESS;\r
380 } else {\r
381\r
382 //\r
383 // Start the GOP software stack.\r
384 //\r
385 Status = QemuVideoGraphicsOutputConstructor (Private);\r
386 ASSERT_EFI_ERROR (Status);\r
387\r
388 Status = gBS->InstallMultipleProtocolInterfaces (\r
389 &Private->Handle,\r
390 &gEfiGraphicsOutputProtocolGuid,\r
391 &Private->GraphicsOutput,\r
392 NULL\r
393 );\r
394 }\r
395\r
396Error:\r
397 if (EFI_ERROR (Status)) {\r
398 if (Private) {\r
399 if (Private->PciIo) {\r
400 if (PciAttributesSaved == TRUE) {\r
401 //\r
402 // Restore original PCI attributes\r
403 //\r
404 Private->PciIo->Attributes (\r
405 Private->PciIo,\r
406 EfiPciIoAttributeOperationSet,\r
407 Private->OriginalPciAttributes,\r
408 NULL\r
409 );\r
410 }\r
411 //\r
412 // Close the PCI I/O Protocol\r
413 //\r
414 gBS->CloseProtocol (\r
415 Private->Handle,\r
416 &gEfiPciIoProtocolGuid,\r
417 This->DriverBindingHandle,\r
418 Private->Handle\r
419 );\r
420 }\r
421\r
422 gBS->FreePool (Private);\r
423 }\r
424 }\r
425\r
426 return Status;\r
427}\r
428\r
429/**\r
430 Stop this device\r
431\r
432 @param This The USB bus driver binding protocol.\r
433 @param Controller The controller to release.\r
434 @param NumberOfChildren The number of children of this device that\r
435 opened the controller BY_CHILD.\r
436 @param ChildHandleBuffer The array of child handle.\r
437\r
438 @retval EFI_SUCCESS The controller or children are stopped.\r
439 @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
440\r
441**/\r
442EFI_STATUS\r
443EFIAPI\r
444QemuVideoControllerDriverStop (\r
445 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
446 IN EFI_HANDLE Controller,\r
447 IN UINTN NumberOfChildren,\r
448 IN EFI_HANDLE *ChildHandleBuffer\r
449 )\r
450{\r
451 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
452\r
453 EFI_STATUS Status;\r
454 QEMU_VIDEO_PRIVATE_DATA *Private;\r
455\r
456 Status = gBS->OpenProtocol (\r
457 Controller,\r
458 &gEfiGraphicsOutputProtocolGuid,\r
459 (VOID **) &GraphicsOutput,\r
460 This->DriverBindingHandle,\r
461 Controller,\r
462 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
463 );\r
464 if (EFI_ERROR (Status)) {\r
465 return Status;\r
466 }\r
467\r
468 //\r
469 // Get our private context information\r
470 //\r
471 Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput);\r
472\r
473 QemuVideoGraphicsOutputDestructor (Private);\r
474 //\r
475 // Remove the GOP protocol interface from the system\r
476 //\r
477 Status = gBS->UninstallMultipleProtocolInterfaces (\r
478 Private->Handle,\r
479 &gEfiGraphicsOutputProtocolGuid,\r
480 &Private->GraphicsOutput,\r
481 NULL\r
482 );\r
483\r
484 if (EFI_ERROR (Status)) {\r
485 return Status;\r
486 }\r
487\r
488 //\r
489 // Restore original PCI attributes\r
490 //\r
491 Private->PciIo->Attributes (\r
492 Private->PciIo,\r
493 EfiPciIoAttributeOperationSet,\r
494 Private->OriginalPciAttributes,\r
495 NULL\r
496 );\r
497\r
498 //\r
499 // Close the PCI I/O Protocol\r
500 //\r
501 gBS->CloseProtocol (\r
502 Controller,\r
503 &gEfiPciIoProtocolGuid,\r
504 This->DriverBindingHandle,\r
505 Controller\r
506 );\r
507\r
508 //\r
509 // Free our instance data\r
510 //\r
511 gBS->FreePool (Private);\r
512\r
513 return EFI_SUCCESS;\r
514}\r
515\r
516/**\r
517 TODO: Add function description\r
518\r
519 @param Private TODO: add argument description\r
520 @param Address TODO: add argument description\r
521 @param Data TODO: add argument description\r
522\r
523 TODO: add return values\r
524\r
525**/\r
526VOID\r
527outb (\r
528 QEMU_VIDEO_PRIVATE_DATA *Private,\r
529 UINTN Address,\r
530 UINT8 Data\r
531 )\r
532{\r
533 Private->PciIo->Io.Write (\r
534 Private->PciIo,\r
535 EfiPciIoWidthUint8,\r
536 EFI_PCI_IO_PASS_THROUGH_BAR,\r
537 Address,\r
538 1,\r
539 &Data\r
540 );\r
541}\r
542\r
543/**\r
544 TODO: Add function description\r
545\r
546 @param Private TODO: add argument description\r
547 @param Address TODO: add argument description\r
548 @param Data TODO: add argument description\r
549\r
550 TODO: add return values\r
551\r
552**/\r
553VOID\r
554outw (\r
555 QEMU_VIDEO_PRIVATE_DATA *Private,\r
556 UINTN Address,\r
557 UINT16 Data\r
558 )\r
559{\r
560 Private->PciIo->Io.Write (\r
561 Private->PciIo,\r
562 EfiPciIoWidthUint16,\r
563 EFI_PCI_IO_PASS_THROUGH_BAR,\r
564 Address,\r
565 1,\r
566 &Data\r
567 );\r
568}\r
569\r
570/**\r
571 TODO: Add function description\r
572\r
573 @param Private TODO: add argument description\r
574 @param Address TODO: add argument description\r
575\r
576 TODO: add return values\r
577\r
578**/\r
579UINT8\r
580inb (\r
581 QEMU_VIDEO_PRIVATE_DATA *Private,\r
582 UINTN Address\r
583 )\r
584{\r
585 UINT8 Data;\r
586\r
587 Private->PciIo->Io.Read (\r
588 Private->PciIo,\r
589 EfiPciIoWidthUint8,\r
590 EFI_PCI_IO_PASS_THROUGH_BAR,\r
591 Address,\r
592 1,\r
593 &Data\r
594 );\r
595 return Data;\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
607UINT16\r
608inw (\r
609 QEMU_VIDEO_PRIVATE_DATA *Private,\r
610 UINTN Address\r
611 )\r
612{\r
613 UINT16 Data;\r
614\r
615 Private->PciIo->Io.Read (\r
616 Private->PciIo,\r
617 EfiPciIoWidthUint16,\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 Index TODO: add argument description\r
631 @param Red TODO: add argument description\r
632 @param Green TODO: add argument description\r
633 @param Blue TODO: add argument description\r
634\r
635 TODO: add return values\r
636\r
637**/\r
638VOID\r
639SetPaletteColor (\r
640 QEMU_VIDEO_PRIVATE_DATA *Private,\r
641 UINTN Index,\r
642 UINT8 Red,\r
643 UINT8 Green,\r
644 UINT8 Blue\r
645 )\r
646{\r
647 outb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index);\r
648 outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2));\r
649 outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2));\r
650 outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2));\r
651}\r
652\r
653/**\r
654 TODO: Add function description\r
655\r
656 @param Private TODO: add argument description\r
657\r
658 TODO: add return values\r
659\r
660**/\r
661VOID\r
662SetDefaultPalette (\r
663 QEMU_VIDEO_PRIVATE_DATA *Private\r
664 )\r
665{\r
666 UINTN Index;\r
667 UINTN RedIndex;\r
668 UINTN GreenIndex;\r
669 UINTN BlueIndex;\r
670\r
671 Index = 0;\r
672 for (RedIndex = 0; RedIndex < 8; RedIndex++) {\r
673 for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) {\r
674 for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) {\r
675 SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6));\r
676 Index++;\r
677 }\r
678 }\r
679 }\r
680}\r
681\r
682/**\r
683 TODO: Add function description\r
684\r
685 @param Private TODO: add argument description\r
686\r
687 TODO: add return values\r
688\r
689**/\r
690VOID\r
691ClearScreen (\r
692 QEMU_VIDEO_PRIVATE_DATA *Private\r
693 )\r
694{\r
695 UINT32 Color;\r
696\r
697 Color = 0;\r
698 Private->PciIo->Mem.Write (\r
699 Private->PciIo,\r
700 EfiPciIoWidthFillUint32,\r
701 0,\r
702 0,\r
703 0x400000 >> 2,\r
704 &Color\r
705 );\r
706}\r
707\r
708/**\r
709 TODO: Add function description\r
710\r
711 @param Private TODO: add argument description\r
712\r
713 TODO: add return values\r
714\r
715**/\r
716VOID\r
717DrawLogo (\r
718 QEMU_VIDEO_PRIVATE_DATA *Private,\r
719 UINTN ScreenWidth,\r
720 UINTN ScreenHeight\r
721 )\r
722{\r
723}\r
724\r
725/**\r
726 TODO: Add function description\r
727\r
728 @param Private TODO: add argument description\r
729 @param ModeData TODO: add argument description\r
730\r
731 TODO: add return values\r
732\r
733**/\r
734VOID\r
212aac55 735InitializeCirrusGraphicsMode (\r
eaf4f336 736 QEMU_VIDEO_PRIVATE_DATA *Private,\r
212aac55 737 QEMU_VIDEO_CIRRUS_MODES *ModeData\r
eaf4f336 738 )\r
739{\r
740 UINT8 Byte;\r
741 UINTN Index;\r
eaf4f336 742\r
743 outw (Private, SEQ_ADDRESS_REGISTER, 0x1206);\r
744 outw (Private, SEQ_ADDRESS_REGISTER, 0x0012);\r
745\r
746 for (Index = 0; Index < 15; Index++) {\r
747 outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]);\r
748 }\r
749\r
212aac55 750 if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) {\r
eaf4f336 751 outb (Private, SEQ_ADDRESS_REGISTER, 0x0f);\r
752 Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30);\r
753 outb (Private, SEQ_DATA_REGISTER, Byte);\r
754 }\r
755\r
756 outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting);\r
757 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506);\r
758 outw (Private, SEQ_ADDRESS_REGISTER, 0x0300);\r
759 outw (Private, CRTC_ADDRESS_REGISTER, 0x2011);\r
760\r
761 for (Index = 0; Index < 28; Index++) {\r
762 outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index));\r
763 }\r
764\r
765 for (Index = 0; Index < 9; Index++) {\r
766 outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index));\r
767 }\r
768\r
769 inb (Private, INPUT_STATUS_1_REGISTER);\r
770\r
771 for (Index = 0; Index < 21; Index++) {\r
772 outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index);\r
773 outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]);\r
774 }\r
775\r
776 outb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
777\r
778 outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009);\r
779 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a);\r
780 outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b);\r
781 outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff);\r
782\r
54f9b9ac 783 SetDefaultPalette (Private);\r
784 ClearScreen (Private);\r
785}\r
786\r
787VOID\r
788BochsWrite (\r
789 QEMU_VIDEO_PRIVATE_DATA *Private,\r
790 UINT16 Reg,\r
791 UINT16 Data\r
792 )\r
793{\r
794 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
795 outw (Private, VBE_DISPI_IOPORT_DATA, Data);\r
796}\r
797\r
798UINT16\r
799BochsRead (\r
800 QEMU_VIDEO_PRIVATE_DATA *Private,\r
801 UINT16 Reg\r
802 )\r
803{\r
804 UINT16 Data;\r
805\r
806 outw (Private, VBE_DISPI_IOPORT_INDEX, Reg);\r
807 Data = inw (Private, VBE_DISPI_IOPORT_DATA);\r
808 return Data;\r
809}\r
810\r
811VOID\r
812InitializeBochsGraphicsMode (\r
813 QEMU_VIDEO_PRIVATE_DATA *Private,\r
814 QEMU_VIDEO_BOCHS_MODES *ModeData\r
815 )\r
816{\r
817 DEBUG ((EFI_D_INFO, "InitializeBochsGraphicsMode: %dx%d @ %d\n",\r
818 ModeData->Width, ModeData->Height, ModeData->ColorDepth));\r
819\r
820 /* unblank */\r
821 outb (Private, ATT_ADDRESS_REGISTER, 0x20);\r
822\r
823 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0);\r
824 BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);\r
825 BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0);\r
826 BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0);\r
827\r
828 BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16) ModeData->ColorDepth);\r
829 BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16) ModeData->Width);\r
830 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16) ModeData->Width);\r
831 BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16) ModeData->Height);\r
832 BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16) ModeData->Height);\r
833\r
834 BochsWrite (Private, VBE_DISPI_INDEX_ENABLE,\r
835 VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);\r
836\r
eaf4f336 837 SetDefaultPalette (Private);\r
838 ClearScreen (Private);\r
839}\r
840\r
841EFI_STATUS\r
842EFIAPI\r
843InitializeQemuVideo (\r
844 IN EFI_HANDLE ImageHandle,\r
845 IN EFI_SYSTEM_TABLE *SystemTable\r
846 )\r
847{\r
848 EFI_STATUS Status;\r
849\r
850 Status = EfiLibInstallDriverBindingComponentName2 (\r
851 ImageHandle,\r
852 SystemTable,\r
853 &gQemuVideoDriverBinding,\r
854 ImageHandle,\r
855 &gQemuVideoComponentName,\r
856 &gQemuVideoComponentName2\r
857 );\r
858 ASSERT_EFI_ERROR (Status);\r
859\r
860 //\r
861 // Install EFI Driver Supported EFI Version Protocol required for\r
862 // EFI drivers that are on PCI and other plug in cards.\r
863 //\r
864 gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion);\r
865 Status = gBS->InstallMultipleProtocolInterfaces (\r
866 &ImageHandle,\r
867 &gEfiDriverSupportedEfiVersionProtocolGuid,\r
868 &gQemuVideoDriverSupportedEfiVersion,\r
869 NULL\r
870 );\r
871 ASSERT_EFI_ERROR (Status);\r
872\r
873 return Status;\r
874}\r