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