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