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