]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
OvmfPkg/VirtioPciDeviceDxe: implement IOMMU-like member functions
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDevice.c
CommitLineData
6fb4e772
OM
1/** @file\r
2\r
3 This driver produces Virtio Device Protocol instances for Virtio Mmio devices.\r
4\r
5 Copyright (C) 2013, ARM Ltd.\r
6\r
7 This program and the accompanying materials are licensed and made available\r
8 under the terms and conditions of the BSD License which accompanies this\r
9 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, WITHOUT\r
13 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/MemoryAllocationLib.h>\r
19#include <Library/UefiBootServicesTableLib.h>\r
20\r
21#include "VirtioMmioDevice.h"\r
22\r
23static VIRTIO_DEVICE_PROTOCOL mMmioDeviceProtocolTemplate = {\r
24 0, // Revision\r
25 0, // SubSystemDeviceId\r
26 VirtioMmioGetDeviceFeatures, // GetDeviceFeatures\r
27 VirtioMmioSetGuestFeatures, // SetGuestFeatures\r
6fb4e772
OM
28 VirtioMmioSetQueueAddress, // SetQueueAddress\r
29 VirtioMmioSetQueueSel, // SetQueueSel\r
30 VirtioMmioSetQueueNotify, // SetQueueNotify\r
31 VirtioMmioSetQueueAlignment, // SetQueueAlign\r
32 VirtioMmioSetPageSize, // SetPageSize\r
33 VirtioMmioGetQueueSize, // GetQueueNumMax\r
34 VirtioMmioSetQueueSize, // SetQueueNum\r
35 VirtioMmioGetDeviceStatus, // GetDeviceStatus\r
36 VirtioMmioSetDeviceStatus, // SetDeviceStatus\r
37 VirtioMmioDeviceWrite, // WriteDevice\r
38 VirtioMmioDeviceRead // ReadDevice\r
39};\r
40\r
41/**\r
42\r
43 Initialize the VirtIo MMIO Device\r
44\r
45 @param[in] BaseAddress Base Address of the VirtIo MMIO Device\r
46\r
47 @param[in, out] Device The driver instance to configure.\r
48\r
49 @retval EFI_SUCCESS Setup complete.\r
50\r
51 @retval EFI_UNSUPPORTED The driver is not a VirtIo MMIO device.\r
52\r
53**/\r
54STATIC\r
55EFI_STATUS\r
56EFIAPI\r
57VirtioMmioInit (\r
58 IN PHYSICAL_ADDRESS BaseAddress,\r
59 IN OUT VIRTIO_MMIO_DEVICE *Device\r
60 )\r
61{\r
62 UINT32 MagicValue;\r
63 UINT32 VendorId;\r
64 UINT32 Version;\r
65\r
66 //\r
67 // Initialize VirtIo Mmio Device\r
68 //\r
69 CopyMem (&Device->VirtioDevice, &mMmioDeviceProtocolTemplate,\r
70 sizeof (VIRTIO_DEVICE_PROTOCOL));\r
71 Device->BaseAddress = BaseAddress;\r
72 Device->VirtioDevice.Revision = VIRTIO_SPEC_REVISION (0, 9, 5);\r
73 Device->VirtioDevice.SubSystemDeviceId =\r
74 MmioRead32 (BaseAddress + VIRTIO_MMIO_OFFSET_DEVICE_ID);\r
75\r
76 //\r
77 // Double-check MMIO-specific values\r
78 //\r
79 MagicValue = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_MAGIC);\r
80 if (MagicValue != VIRTIO_MMIO_MAGIC) {\r
81 return EFI_UNSUPPORTED;\r
82 }\r
83\r
84 Version = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VERSION);\r
85 if (Version != 1) {\r
86 return EFI_UNSUPPORTED;\r
87 }\r
88\r
89 //\r
90 // Double-check MMIO-specific values\r
91 //\r
92 VendorId = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VENDOR_ID);\r
93 if (VendorId != VIRTIO_VENDOR_ID) {\r
94 //\r
95 // The ARM Base and Foundation Models do not report a valid VirtIo VendorId.\r
96 // They return a value of 0x0 for the VendorId.\r
97 //\r
98 DEBUG((EFI_D_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "\r
99 "match the VirtIo VendorId (0x%X).\n",\r
100 VendorId, VIRTIO_VENDOR_ID));\r
101 }\r
102\r
103 return EFI_SUCCESS;\r
104}\r
105\r
106\r
107/**\r
108\r
109 Uninitialize the internals of a virtio-mmio device that has been successfully\r
110 set up with VirtioMmioInit().\r
111\r
112 @param[in, out] Device The device to clean up.\r
113\r
114**/\r
115\r
116STATIC\r
117VOID\r
118EFIAPI\r
119VirtioMmioUninit (\r
120 IN VIRTIO_MMIO_DEVICE *Device\r
121 )\r
122{\r
123 //\r
124 // Note: This function mirrors VirtioMmioInit() that does not allocate any\r
125 // resources - there's nothing to free here.\r
126 //\r
127}\r
128\r
129EFI_STATUS\r
130VirtioMmioInstallDevice (\r
131 IN PHYSICAL_ADDRESS BaseAddress,\r
132 IN EFI_HANDLE Handle\r
133 )\r
134{\r
135 EFI_STATUS Status;\r
136 VIRTIO_MMIO_DEVICE *VirtIo;\r
137\r
138 if (!BaseAddress) {\r
139 return EFI_INVALID_PARAMETER;\r
140 }\r
141 if (Handle == NULL) {\r
142 return EFI_INVALID_PARAMETER;\r
143 }\r
144\r
145 //\r
146 // Allocate VIRTIO_MMIO_DEVICE\r
147 //\r
148 VirtIo = AllocateZeroPool (sizeof (VIRTIO_MMIO_DEVICE));\r
149 if (VirtIo == NULL) {\r
150 return EFI_OUT_OF_RESOURCES;\r
151 }\r
152\r
153 VirtIo->Signature = VIRTIO_MMIO_DEVICE_SIGNATURE;\r
154\r
155 Status = VirtioMmioInit (BaseAddress, VirtIo);\r
156 if (EFI_ERROR (Status)) {\r
157 goto FreeVirtioMem;\r
158 }\r
159\r
160 //\r
161 // Install VIRTIO_DEVICE_PROTOCOL to Handle\r
162 //\r
163 Status = gBS->InstallProtocolInterface (&Handle,\r
164 &gVirtioDeviceProtocolGuid, EFI_NATIVE_INTERFACE,\r
165 &VirtIo->VirtioDevice);\r
166 if (EFI_ERROR (Status)) {\r
167 goto UninitVirtio;\r
168 }\r
169\r
170 return EFI_SUCCESS;\r
171\r
172UninitVirtio:\r
173 VirtioMmioUninit (VirtIo);\r
174\r
175FreeVirtioMem:\r
176 FreePool (VirtIo);\r
177 return Status;\r
178}\r
179\r
180EFI_STATUS\r
181VirtioMmioUninstallDevice (\r
182 IN EFI_HANDLE DeviceHandle\r
183 )\r
184{\r
185 VIRTIO_DEVICE_PROTOCOL *VirtioDevice;\r
186 VIRTIO_MMIO_DEVICE *MmioDevice;\r
187 EFI_STATUS Status;\r
188\r
189 Status = gBS->OpenProtocol (\r
190 DeviceHandle, // candidate device\r
191 &gVirtioDeviceProtocolGuid, // retrieve the VirtIo iface\r
192 (VOID **)&VirtioDevice, // target pointer\r
193 DeviceHandle, // requestor driver identity\r
194 DeviceHandle, // requesting lookup for dev.\r
195 EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added\r
196 );\r
197 if (EFI_ERROR (Status)) {\r
198 return Status;\r
199 }\r
200\r
201 //\r
202 // Get the MMIO device from the VirtIo Device instance\r
203 //\r
204 MmioDevice = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (VirtioDevice);\r
205\r
206 //\r
207 // Uninstall the protocol interface\r
208 //\r
209 Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
210 &gVirtioDeviceProtocolGuid, &MmioDevice->VirtioDevice\r
211 );\r
212 if (EFI_ERROR (Status)) {\r
213 return Status;\r
214 }\r
215\r
216 //\r
217 // Uninitialize the VirtIo Device\r
218 //\r
219 VirtioMmioUninit (MmioDevice);\r
220 FreePool (MmioDevice);\r
221\r
222 return EFI_SUCCESS;\r
223}\r