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